⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxy.c

📁 这是一个C程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    * Route present?    * If so, fetch address from topmost Route: header and remove it.    */#endif   /*    * destination from SIP URI    */   } else {      /* get the destination from the SIP URI */      sts = get_ip_by_host(url->host, &sendto_addr);      if (sts == STS_FAILURE) {         DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]",                url->host);         return STS_FAILURE;      }      if (url->port) {         port=atoi(url->port);         if ((port<=0) || (port>65535)) port=SIP_PORT;      } else {         port=SIP_PORT;      }      DEBUGC(DBCLASS_PROXY, "proxy_request: have SIP URI to %s:%i",             url->host, port);   }   /*    * RFC 3261, Section 16.6 step 8    * Proxy Behavior - Add a Via header field value    */   /* add my Via header line (outbound interface)*/   if (type == REQTYP_INCOMING) {      sts = sip_add_myvia(ticket, IF_INBOUND);      if (sts == STS_FAILURE) {         ERROR("adding my inbound via failed!");      }   } else {      sts = sip_add_myvia(ticket, IF_OUTBOUND);      if (sts == STS_FAILURE) {         ERROR("adding my outbound via failed!");         return STS_FAILURE;      }   }  /*   * RFC 3261, Section 16.6 step 9   * Proxy Behavior - Add a Content-Length header field if necessary   */  /* not necessary, already in message and we do not support TCP */  /*   * RFC 3261, Section 16.6 step 10   * Proxy Behavior - Forward the new request   */   sts = sip_message_to_str(request, &buffer, &buflen);   if (sts != 0) {      ERROR("proxy_request: sip_message_to_str failed");      return STS_FAILURE;   }   sipsock_send(sendto_addr, port, ticket->protocol,                buffer, buflen);    osip_free (buffer);  /*   * RFC 3261, Section 16.6 step 11   * Proxy Behavior - Set timer C   */  /* NOT IMPLEMENTED - does this really apply for stateless proxies? */   return STS_SUCCESS;}/* * PROXY_RESPONSE * * RETURNS *	STS_SUCCESS on success *	STS_FAILURE on error * RFC3261 *    Section 16.7: Proxy Behavior - Response Processing *    1.  Find the appropriate response context *    2.  Update timer C for provisional responses *    3.  Remove the topmost Via *    4.  Add the response to the response context *    5.  Check to see if this response should be forwarded immediately *    6.  When necessary, choose the best final response from the *        response context *    7.  Aggregate authorization header field values if necessary *    8.  Optionally rewrite Record-Route header field values *    9.  Forward the response *    10. Generate any necessary CANCEL requests  * */int proxy_response (sip_ticket_t *ticket) {   int sts;   int type;   struct in_addr sendto_addr;   osip_via_t *via;   int port;   char *buffer;   size_t buflen;   osip_message_t *response;   DEBUGC(DBCLASS_PROXY,"proxy_response");   if (ticket==NULL) {      ERROR("proxy_response: called with NULL ticket");      return STS_FAILURE;   }   response=ticket->sipmsg;   /*    * RFC 3261, Section 16.7 step 3    * Proxy Behavior - Response Processing - Remove my Via header field value    */   /* remove my Via header line */   sts = sip_del_myvia(ticket);   if (sts == STS_FAILURE) {      DEBUGC(DBCLASS_PROXY,"not addressed to my VIA, ignoring response");      return STS_FAILURE;   }   /*    * figure out if this is an request coming from the outside    * world to one of our registered clients    */    sip_find_direction(ticket, NULL);    type = ticket->direction;/* * ok, we got a response that we are allowed to process. */   switch (type) {  /*   * from an external host to the internal masqueraded host   */   case RESTYP_INCOMING:      DEBUGC(DBCLASS_PROXY,"incoming response for %s@%s from outbound",	response->from->url->username? response->from->url->username:"*NULL*",	response->from->url->host? response->from->url->host : "*NULL*");sts=sip_obscure_callid(ticket);      /*       * Response for INVITE - deal with RTP data in body and       *                       start RTP proxy stream(s). In case       *                       of a negative answer, stop RTP stream       */      if (MSG_IS_RESPONSE_FOR(response,"INVITE")) {         /* positive response, start RTP stream */         if ((MSG_IS_STATUS_1XX(response)) ||               (MSG_IS_STATUS_2XX(response))) {            if (configuration.rtp_proxy_enable == 1) {               sts = proxy_rewrite_invitation_body(ticket, DIR_INCOMING);            }         /* negative - stop a possibly started RTP stream */         } else if ((MSG_IS_STATUS_4XX(response))  ||                     (MSG_IS_STATUS_5XX(response)) ||                     (MSG_IS_STATUS_6XX(response))) {            rtp_stop_fwd(osip_message_get_call_id(response), DIR_INCOMING);            rtp_stop_fwd(osip_message_get_call_id(response), DIR_OUTGOING);         }      } /* if INVITE */      /*       * Response for REGISTER - special handling of Contact header       */      if (MSG_IS_RESPONSE_FOR(response,"REGISTER")) {         /*          * REGISTER returns *my* Contact header information.          * Rewrite Contact header back to represent the true address.          * Other responses do return the Contact header of the sender.          * also change the expiration timeout to the value returned by the          * server.          */         sts = register_set_expire(ticket);         sip_rewrite_contact(ticket, DIR_INCOMING);      }      /*        * Response for SUBSCRIBE       *       * HACK for Grandstream SIP phones (with newer firmware like 1.0.4.40):       *   They send a SUBSCRIBE request to the registration server. In       *   case of beeing registering directly to siproxd, this request of       *   course will eventually be forwarded back to the same UA.       *   Grandstream then does reply with an '202' response (A 202       *   response merely indicates that the subscription has been       *   understood, and that authorization may or may not have been       *   granted), which then of course is forwarded back to the phone.       *   And it seems that the Grandstream can *not* *handle* this       *   response, as it immediately sends another SUBSCRIBE request.       *   And this games goes on and on and on...       *       *   As a workaround we will transform any 202 response to a       *   '404 unknown destination'       *          */{      osip_header_t *ua_hdr=NULL;      osip_message_get_user_agent(response, 0, &ua_hdr);      if (ua_hdr && ua_hdr->hvalue &&          (osip_strncasecmp(ua_hdr->hvalue,"grandstream", 11)==0) &&          (MSG_IS_RESPONSE_FOR(response,"SUBSCRIBE")) &&          (MSG_TEST_CODE(response, 202))) {         DEBUGC(DBCLASS_PROXY, "proxy_response: Grandstream hack 202->404");         response->status_code=404;      }}      break;     /*   * from the internal masqueraded host to an external host   */   case RESTYP_OUTGOING:      DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound",	     response->from->url->username ?                response->from->url->username : "*NULL*",	     response->from->url->host ?                 response->from->url->host : "*NULL*");sts=sip_obscure_callid(ticket);      /* Rewrite Contact header to represent the masqued address */      sip_rewrite_contact(ticket, DIR_OUTGOING);      /* Masquerade the User-Agent if configured to do so */      proxy_rewrite_useragent(ticket);      /*       * If an 2xx OK or 1xx response, answer to an INVITE request,       * rewrite body       *       * In case of a negative answer, stop RTP stream       */      if (MSG_IS_RESPONSE_FOR(response,"INVITE")) {         /* positive response, start RTP stream */         if ((MSG_IS_STATUS_1XX(response)) ||               (MSG_IS_STATUS_2XX(response))) {            /* This is an outgoing response, therefore an outgoing stream */            sts = proxy_rewrite_invitation_body(ticket, DIR_OUTGOING);         /* megative - stop a possibly started RTP stream */         } else if ((MSG_IS_STATUS_4XX(response))  ||                     (MSG_IS_STATUS_5XX(response)) ||                     (MSG_IS_STATUS_6XX(response))) {            rtp_stop_fwd(osip_message_get_call_id(response), DIR_INCOMING);            rtp_stop_fwd(osip_message_get_call_id(response), DIR_OUTGOING);         }      } /* if INVITE */      break;      default:      DEBUGC(DBCLASS_PROXY, "response from/to unregistered UA (%s@%s)",	   response->from->url->username? response->from->url->username:"*NULL*",	   response->from->url->host? response->from->url->host : "*NULL*");      return STS_FAILURE;   }   /*    * for ALL incoming response include my Record-Route header.    * The local UA will probably send its answer to the topmost     * Route Header (8.1.2 of RFC3261)    */    if (type == RESTYP_INCOMING) {       DEBUGC(DBCLASS_PROXY,"Adding my Record-Route");       route_add_recordroute(ticket);    } else {       /*        * outgoing packets must not have my record route header, as        * this likely will contain a private IP address (my inbound).        */       DEBUGC(DBCLASS_PROXY,"Purging Record-Routes (outgoing packet)");       route_purge_recordroute(ticket);    }   /*    * Determine Next-Hop Address    *//*&&&& priority probably should be: * 1) Route header * 2) fixed outbound proxy * 3) SIP URI */   /*    * check if we need to send to an outbound proxy    */// let's try with Route header first#if 0   if ((type == RESTYP_OUTGOING) &&       (sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {      DEBUGC(DBCLASS_PROXY, "proxy_response: have outbound proxy %s:%i",             utils_inet_ntoa(sendto_addr), port);   /*    * Route present?    * If so, fetch address from topmost Route: header and remove it.    */   } else if ((type == RESTYP_OUTGOING) &&               (!osip_list_eol(&(response->routes), 0))) {      sts=route_determine_nexthop(ticket, &sendto_addr, &port);      if (sts == STS_FAILURE) {         DEBUGC(DBCLASS_PROXY, "proxy_response: route_determine_nexthop failed");         return STS_FAILURE;      }      DEBUGC(DBCLASS_PROXY, "proxy_response: have Route header to %s:%i",             utils_inet_ntoa(sendto_addr), port);#else   if ((type == RESTYP_OUTGOING) &&               (!osip_list_eol(&(response->routes), 0))) {      sts=route_determine_nexthop(ticket, &sendto_addr, &port);      if (sts == STS_FAILURE) {         DEBUGC(DBCLASS_PROXY, "proxy_response: route_determine_nexthop failed");         return STS_FAILURE;      }      DEBUGC(DBCLASS_PROXY, "proxy_response: have Route header to %s:%i",             utils_inet_ntoa(sendto_addr), port);   } else if ((type == RESTYP_OUTGOING) &&       (sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {      DEBUGC(DBCLASS_PROXY, "proxy_response: have outbound proxy %s:%i",             utils_inet_ntoa(sendto_addr), port);   /*    * Route present?    * If so, fetch address from topmost Route: header and remove it.    */#endif   } else {      /* get target address and port from VIA header */      via = (osip_via_t *) osip_list_get (&(response->vias), 0);      if (via == NULL) {         ERROR("proxy_response: list_get via failed");         return STS_FAILURE;      }      sts = get_ip_by_host(via->host, &sendto_addr);      if (sts == STS_FAILURE) {         DEBUGC(DBCLASS_PROXY, "proxy_response: cannot resolve VIA [%s]",                via->host);         return STS_FAILURE;      }      if (via->port) {         port=atoi(via->port);         if ((port<=0) || (port>65535)) port=SIP_PORT;      } else {         port=SIP_PORT;      }   }   sts = sip_message_to_str(response, &buffer, &buflen);   if (sts != 0) {      ERROR("proxy_response: sip_message_to_str failed");      return STS_FAILURE;   }   sipsock_send(sendto_addr, port, ticket->protocol,                buffer, buflen);    osip_free (buffer);   return STS_SUCCESS;}/* * PROXY_REWRITE_INVITATION_BODY * * rewrites the outgoing INVITATION request or response packet *  * RETURNS *	STS_SUCCESS on success *	STS_FAILURE on error */int proxy_rewrite_invitation_body(sip_ticket_t *ticket, int direction){   osip_message_t *mymsg=ticket->sipmsg;   osip_body_t *body;   sdp_message_t  *sdp;   struct in_addr map_addr, addr_sess, addr_media, outside_addr, inside_addr;   int sts;   char *buff;   size_t buflen;   char clen[8]; /* content length: probably never more than 7 digits !*/   int map_port, msg_port;   int media_stream_no;   sdp_connection_t *sdp_conn;   sdp_media_t *sdp_med;   int rtp_direction=0;   int have_c_media=0;   int isrtp = 0 ;   if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS;   /*    * get SDP structure    */   sts = osip_message_get_body(mymsg, 0, &body);   if (sts != 0) {      DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: "                            "no body found in message");      return STS_SUCCESS;   }   sts = sip_body_to_str(body, &buff, &buflen);   if (sts != 0) {      ERROR("rewrite_invitation_body: unable to sip_body_to_str");      return STS_FAILURE;   }   DEBUGC(-1, "rewrite_invitation_body: payload %ld bytes", (long)buflen);   DUMP_BUFFER(-1, buff, buflen);   sts = sdp_message_init(&sdp);   sts = sdp_message_parse (sdp, buff);   if (sts != 0) {      ERROR("rewrite_invitation_body: unable to sdp_message_parse body");      DUMP_BUFFER(-1, buff, buflen);      osip_free(buff);      sdp_message_free(sdp);      return STS_FAILURE;   }   osip_free(buff);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -