@@ -160,6 +160,17 @@
        struct sip_codec_pref *next;
 } *prefs;
 
+struct sip_redir_uri {
+        char uri[256];
+        struct sip_redir_uri *next;
+};
+
+struct sip_redir {
+       char exten[256];
+        struct sip_redir_uri *redir_uri;
+       struct sip_redir *next;
+};
+
 struct sip_request {
   char *rlPart1; /* SIP Method Name or "SIP/2.0" protocol version */
   char *rlPart2; /* The Request URI or Response Status */
@@ -354,6 +365,10 @@
        ast_mutex_t lock;
 } peerl = { NULL, AST_MUTEX_INITIALIZER };
 
+static struct ast_redir_list {
+       struct sip_redir *redirs;
+       ast_mutex_t lock;
+} redirl = { NULL, AST_MUTEX_INITIALIZER };
 
 #define REG_STATE_UNREGISTERED 0
 #define REG_STATE_REGSENT         1
@@ -419,6 +434,7 @@
 static int build_reply_digest(struct sip_pvt *p, char *orig_header, char *digest, int digest_len);
 static int find_user(struct sip_pvt *fup, int event);
 static void prune_peers(void);
+static struct sip_redir *sip_match_context(struct sip_request *req);
 
 static int __sip_xmit(struct sip_pvt *p, char *data, int len)
 {
@@ -2237,9 +2253,12 @@
        return 0;
 }
 
+
 static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, struct sip_request *req)
 {
        char newto[256] = "", *ot;
+       struct sip_redir *redir;
+       struct sip_redir_uri *redir_uri;
        memset(resp, 0, sizeof(*resp));
        init_resp(resp, msg, req);
        copy_via_headers(p, resp, req, "Via");
@@ -2272,7 +2291,19 @@
                add_header(resp, "Expires", tmp);
                add_header(resp, "Contact", contact);
        } else {
-               add_header(resp, "Contact", p->our_contact);
+               if( msg[0] == '3' ) {
+                       redir = sip_match_context(req);
+                       redir_uri = redir->redir_uri;
+                       while(redir_uri->uri) {
+                               char contact[256];
+                               sprintf(contact,"<%s>",redir_uri->uri);
+                               add_header(resp, "Contact", contact);
+                               redir_uri = redir_uri->next;
+                       } 
+               }
+               else
+                       add_header(resp, "Contact", p->our_contact);
+
        }
        return 0;
 }
@@ -4988,11 +5019,60 @@
        return 0;
 }
 
+
+static struct sip_redir *sip_match_context(struct sip_request *req)
+{
+   // printf("SIP Request Variables: %s\r\n ",req->rlPart2);
+       struct sip_redir *redir;
+       char copy[256] = "";
+        char *username=NULL, *hostname=NULL, *secret=NULL, *authuser=NULL;
+        char *porta=NULL;
+        char *stringp=NULL;
+
+        strncpy(copy, &req->rlPart2[4], sizeof(copy)-1);
+        stringp=copy;
+        username = stringp;
+        hostname = strrchr(stringp, '@');
+        if (hostname) {
+                *hostname = '\0';
+                hostname++;
+        }
+        stringp=username;
+        username = strsep(&stringp, ":");
+        if (username) {
+                secret = strsep(&stringp, ":");
+                if (secret)
+                       authuser = strsep(&stringp, ":");
+        }
+        stringp = hostname;
+        porta = strrchr(stringp, ':');
+        if( porta ) {
+               *porta = '\0';
+               porta++;
+       }
+       printf("\r\nUsername is: %s\r\n",username);
+       ast_mutex_lock(&redirl.lock);
+        for (redir=redirl.redirs;redir;) {
+               printf("\r\n%s\r\n",redir->exten);
+          if(!strcasecmp(redir->exten,username) ) 
+               break;
+          redir = redir->next;
+       }
+       ast_mutex_unlock(&redirl.lock);
+
+       if( redir )
+               return redir;
+
+       return NULL;
+}
+
+
 static int handle_request(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount)
 {
        /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things
           relatively static */
        struct sip_request resp;
+       struct sip_redir *redir;
        char *cmd;
        char *cseq;
        char *from;
@@ -5088,6 +5168,14 @@
                if (!p->lastinvite)
                        p->needdestroy = 1;
        } else if (!strcasecmp(cmd, "INVITE")) {
+ 
+               ast_log(LOG_DEBUG,"Got an Invite request \r\n");
+               redir = sip_match_context(req);
+               if (redir){
+                       transmit_response(p, "300 Redirecting", req);
+                       return 0;
+               }
+
                if (p->outgoing && p->owner && (p->owner->_state != AST_STATE_UP)) {
                        /* This is a call to ourself.  Send ourselves an error code and stop
                           processing immediately, as SIP really has no good mechanism for
@@ -5823,6 +5911,34 @@
        return tmpc;
 }
 
+static struct sip_redir *build_redir(char *name, struct ast_variable *v)
+{
+       struct sip_redir *redir;
+       struct sip_redir_uri *redir_uri=NULL;
+       redir = (struct sip_redir *)malloc(sizeof(struct sip_redir));
+       if (redir) {
+               memset(redir, 0, sizeof(struct sip_redir));
+               strncpy(redir->exten, name, sizeof(redir->exten)-1);
+               while(v) {
+                       if (!strcasecmp(v->name, "redirecturi")) {
+                       /*      printf("\r\n Redirection URI Found: %s\r\n",v->value);
+                       */      if (!redir_uri) {
+                                       redir_uri = (struct sip_redir_uri *)malloc(sizeof(struct sip_redir_uri));
+                                       redir->redir_uri = redir_uri;
+                                       strcpy(redir_uri->uri,v->value);
+                               }
+                               else {
+                                       redir_uri->next = (struct sip_redir_uri *)malloc(sizeof(struct sip_redir_uri));
+                                       redir_uri = redir_uri->next;
+                                       strcpy(redir_uri->uri,v->value);
+                               }
+                       }
+                       v = v->next;
+               }
+       }
+       return redir;
+}
+
 static struct sip_user *build_user(char *name, struct ast_variable *v)
 {
        struct sip_user *user;
@@ -6129,8 +6245,10 @@
        struct ast_variable *v;
        struct sip_peer *peer;
        struct sip_user *user;
+       struct sip_redir *redir;
        char *cat;
-    char *utype;
+       char *utype;
+       char *redirection;
        struct hostent *hp;
        int format;
        int oldport = ntohs(bindaddr.sin_port);
@@ -6279,6 +6397,22 @@
 
        cat = ast_category_browse(cfg, NULL);
        while(cat) {
+                /* check if redirection present */
+                redirection = ast_variable_retrieve(cfg, cat, "redirect");
+               if (redirection) {
+                       ast_log(LOG_DEBUG,"Redirection Found Entity : %s\r\n",cat);
+                       if (!strcasecmp(redirection, "yes")) {
+                               redir = build_redir(cat, ast_variable_browse(cfg,cat));
+                               if (redir) {
+                                       ast_mutex_lock(&redirl.lock);
+                                       redir->next = redirl.redirs;
+                                       redirl.redirs = redir;
+                                       ast_mutex_unlock(&redirl.lock);
+                               }
+                       }
+               }
+                 
+ 
                if (strcasecmp(cat, "general")) {
                        utype = ast_variable_retrieve(cfg, cat, "type");
                        if (utype) {
@@ -6549,11 +6683,34 @@
        ast_mutex_unlock(&peerl.lock);
 }
 
+static void delete_redirs(void)
+{
+       /* Delete all redirs */
+       struct sip_redir *redir, *redirlast, *redirnext;
+       struct sip_redir_uri *deluri, *urinext;
+       ast_mutex_lock(&redirl.lock);
+       redirlast = NULL;
+       for (redir=redirl.redirs;redir;) {
+               redirnext = redir->next;
+               /* clear all the uris related to this context */
+               if( !(!redir->redir_uri) )
+               for (deluri=redir->redir_uri;deluri;) {
+                       urinext = deluri->next;
+                       free(deluri);
+                       deluri = urinext;
+               }
+               free(redir);
+               redir = redirnext;
+       }
+       ast_mutex_unlock(&redirl.lock);
+}
+
 int reload(void)
 {
        struct sip_registry *reg;
        struct sip_peer *peer;
        delete_users();
+        delete_redirs();
        reload_config();
 
        prune_peers();