📄 udp.c
字号:
FD_SET (ctx->out_socket, &memo_fdset); if (ctx->mcast_socket>0 &&ctx->mcast_socket!=ctx->in_socket) FD_SET (ctx->mcast_socket, &memo_fdset); /* create a set of file descritor to control the stack */ for (; max != 0; max--) { osip_fdset = memo_fdset; max_fd = ctx->in_socket; if (max_fd < ctx->out_socket) max_fd = ctx->out_socket; if (max_fd < ctx->mcast_socket) max_fd = ctx->mcast_socket; i = select (max_fd + 1, &osip_fdset, NULL, NULL, NULL); buf = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH * sizeof (char) + 3); if (ipv6_enable==1) { slen = sizeof (sa6); sa = (struct sockaddr *)&sa6; } else { slen = sizeof (sa4); sa = (struct sockaddr *)&sa4; } if (0 == i) { osip_free (buf); return -1; /* no message: timout expires */ } else if (-1 == i) { osip_free (buf); return -2; /* error */ } else if (FD_ISSET (ctx->in_socket, &osip_fdset)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "UDP MESSAGE RECEIVED\n")); i = ppl_socket_recv (ctx->in_socket, buf, SIP_MESSAGE_MAX_LENGTH, 0, sa, &slen); } else if (ctx->out_socket!=ctx->in_socket &&FD_ISSET (ctx->out_socket, &osip_fdset)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "UDP MESSAGE RECEIVED\n")); i = ppl_socket_recv (ctx->out_socket, buf, SIP_MESSAGE_MAX_LENGTH, 0, sa, &slen); } else if (ctx->mcast_socket>0 &&FD_ISSET (ctx->mcast_socket, &osip_fdset)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "UDP MULTICAST MESSAGE RECEIVED\n")); i = ppl_socket_recv (ctx->mcast_socket, buf, SIP_MESSAGE_MAX_LENGTH, 0, sa, &slen); } if (i > 0) { char *ip_address = ppl_inet_ntop (sa); /* Message might not end with a "\0" but we know the number of */ /* char received! */ osip_strncpy (buf + i, "\0", 1); if (ip_address==NULL) { osip_free(buf); return -1; /* missing information from socket?? */ } if (ipv6_enable==1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "udp plugin: RCV UDP MESSAGE (from %s:%i)\n", ip_address, ntohs (sa6.sin6_port))); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "udp plugin: RCV UDP MESSAGE (from %s:%i)\n", /* inet_ntoa (sa.sin_addr), ntohs (sa.sin_port))); */ ip_address, ntohs (sa4.sin_port))); } if (ctx->mcast_socket>0) { /* check maddr parameter to detect multicast data */ /* do they need special processing? */ }#ifndef HIDE_MESSAGE OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "\n%s\n", buf));#endif if (ipv6_enable==1) udp_process_message (buf, ip_address, ntohs (sa6.sin6_port), i); else udp_process_message (buf, ip_address, /* inet_ntoa (sa.sin_addr), */ ntohs (sa4.sin_port), i); osip_free(ip_address); } else if (i == -1) { if (errno == EAGAIN) { osip_free (buf); return 0; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "udp plugin: error while receiving data!\n")); osip_free (buf); return -1; } } /* max is reached */ return 1;}static int__osip_message_fix_last_via_header (osip_message_t * request, char *ip_addr, int port){ osip_generic_param_t *rport; osip_via_t *via; /* get Top most Via header: */ if (request == NULL || request == NULL) return -1; if (MSG_IS_RESPONSE (request)) return 0; /* Don't fix Via header */ via = osip_list_get (request->vias, 0); if (via == NULL || via->host == NULL) /* Hey, we could build it? */ return -1; osip_via_param_get_byname (via, "rport", &rport); /* detect rport */ if (rport != NULL) { if (rport->gvalue == NULL) { rport->gvalue = (char *) osip_malloc (9);#ifdef WIN32 _snprintf (rport->gvalue, 8, "%i", port);#else snprintf (rport->gvalue, 8, "%i", port);#endif } /* else bug? */ } /* only add the received parameter if the 'sent-by' value does not contains this ip address */ if (0 == osip_strcasecmp (via->host, ip_addr)) /* don't need the received parameter */ return 0; else osip_via_set_received (via, osip_strdup (ip_addr)); return 0;}intudp_process_message (char *buf, char *ip_addr, int port, int length){ osip_event_t *evt; if (buf == NULL || *buf == '\0' || buf[1] == '\0' || buf[2] == '\0' || buf[3] == '\0' || buf[4] == '\0' || buf[5] == '\0') { osip_free (buf); return -1; } evt = osip_parse (buf, length); osip_free (buf); if (evt == NULL) /* discard... */ { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "udp module: Could not parse response!\n")); return -1; } if (evt->sip == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "udp module: Could not parse response!\n")); osip_event_free (evt); return -1; } udp_log_event (evt); /* modify the request to add a "received" parameter in the last Via. */ /* for libosip>0.9.2 use osip_message_fix_last_via_header from osip */ __osip_message_fix_last_via_header (evt->sip, ip_addr, port); if (evt->sip == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "udp module: Probably a bad via header!\n")); osip_event_free (evt); return -1; } /* modify the request so it's compliant with the latest draft */ psp_core_fix_strict_router_issue (evt); psp_core_event_add_sip_message (evt); return 0;}intudp_log_event (osip_event_t * evt){#ifdef SHOW_LIMITED_MESSAGE osip_via_t *via; osip_generic_param_t *b; via = osip_list_get (evt->sip->vias, 0); osip_via_param_get_byname (via, "branch", &b); if (b == NULL) { if (MSG_IS_REQUEST (evt->sip)) { } else { } return -1; } if (MSG_IS_REQUEST (evt->sip)) { } else { }#endif return 0;}static int udp_plugin_get_new_socket(struct sockaddr_storage *addr){ struct sockaddr_in6 raddr6; struct sockaddr_in raddr; int option; int i; int socket; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "udp plugin: Building a new connect socket %i!\n", ctx->in_port)); if (ipv6_enable==1) socket = ppl_socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP); else socket = ppl_socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (socket == -1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "udp plugin: cannot create descriptor for port %i!\n")); return -1; } option = 1; i = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, OPTVALCAST &option, sizeof option); if (i!=0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "upd plugin; UDP listener SO_REUSE_ADDR failed %i (%i)!\n", ctx->in_port, i)); } if (ipv6_enable==1) { memcpy ((void *)&(raddr6.sin6_addr.s6_addr), (const void *)&in6addr_any, 16); raddr6.sin6_port = htons (0); raddr6.sin6_family = AF_INET6; i = ppl_socket_bind (socket, (struct sockaddr *) &raddr6, sizeof (raddr6)); } else { raddr.sin_addr.s_addr = htons (INADDR_ANY); raddr.sin_port = htons (0); raddr.sin_family = AF_INET; i = ppl_socket_bind (socket, (struct sockaddr *) &raddr, sizeof (raddr)); } if (i < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "udp plugin: cannot bind on port %i!\n", ctx->in_port)); ppl_socket_close(socket); return -1; } i = connect(socket,(struct sockaddr *) addr,sizeof(struct sockaddr)); if (i < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "udp plugin: cannot connect socket %i!\n", ctx->in_port)); ppl_socket_close(socket); return -1; } return socket;}/* return -1 on error 0 on success*/intcb_snd_udp_message (osip_transaction_t * transaction, /* read only element */ osip_message_t * message, /* message to send */ char *host, /* proposed destination host */ int port, /* proposed destination port */ int socket) /* proposed socket (if any) */{ size_t length; int i; char *buf; int sock; struct addrinfo *addrinfo; struct sockaddr_storage addr; if (ctx == NULL) return -1; i = osip_message_to_str (message, &buf, &length); if (i != 0) return -1;#ifndef HIDE_MESSAGE OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "\n%s\n", buf));#endif /* For RESPONSE, oSIP ALWAYS provide host and port from the top via */ /* For REQUEST, oSIP SOMETIMES provide host and port to use which may be different from the request uri */ if (host == NULL) { /* when host is NULL, we use the request uri value */ host = message->req_uri->host; if (message->req_uri->port != NULL) port = osip_atoi (message->req_uri->port); else port = 5060; } i = ppl_dns_get_addrinfo(&addrinfo, host, port); if (i!=PPL_SUCCESS) { osip_free (buf); return -1; }#if 0 memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); freeaddrinfo (addrinfo);#endif /* #define SUPPORT_ICMP */#ifdef SUPPORT_ICMP sock = 0; /* use the default */ if (transaction!=NULL) { if (MSG_IS_ACK(message)) { if (transaction->out_socket!=0 && transaction->out_socket!=-1) { ppl_socket_close(transaction->out_socket); transaction->out_socket = 0; } } if (MSG_IS_REQUEST(message)) { if (transaction->out_socket==0 || transaction->out_socket==-1) transaction->out_socket = udp_plugin_get_new_socket(&addr); if (transaction->out_socket==0 || transaction->out_socket==-1) /* use default for ACK */ transaction->out_socket = 0; } } /* connect(sock,(struct sockaddr *) &addr,sizeof(addr)); */#endif#ifdef SUPPORT_ICMP if (MSG_IS_RESPONSE(message) || MSG_IS_ACK(message) || transaction->out_socket==0) i = sendto (ctx->out_socket, (const void *) buf, length, 0, (struct sockaddr *) &addr, sizeof (addr)); else i = send (transaction->out_socket, (const void *) buf, length, 0); #else sock = ctx->out_socket; i = sendto (sock, (const void *) buf, length, 0, addrinfo->ai_addr, addrinfo->ai_addrlen); /*(struct sockaddr *) &addr, sizeof (addr)); */ freeaddrinfo (addrinfo);#endif if (0 > i) { osip_free (buf);#ifdef WIN32 i = WSAGetLastError (); if (WSAECONNREFUSED == i) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SIP_ECONNREFUSED - No remote server.\n")); return 1; /* I prefer to answer 1 by now.. we'll see later what's better */ }#else i = errno; if (ECONNREFUSED == i) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SIP_ECONNREFUSED - No remote server.\n")); return 1; /* I prefer to answer 1 by now.. we'll see later what's better */ }#endif#ifdef WIN32 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SIP_NETWORK_ERROR - Network error %i sending message to %s on port %i.\n", i, host, port));#else /* XXX use some configure magic to detect if we have the right strerror_r() * function (the one that returns int, not char *) and then use strerror_r() * instead. */ OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SIP_NETWORK_ERROR - Network error %i (%s) sending message to %s on port %i.\n", i, strerror (i), host, port));#endif /* SIP_NETWORK_ERROR; */ return -1; }#ifdef WIN32 i = WSAGetLastError (); if (WSAECONNREFUSED == i) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SIP_ECONNREFUSED - No remote server.\n")); return 1; } if (WSAECONNRESET == i) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SIP_ECONNREFUSED - No remote server.\n")); return 1; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "WSAGetLastError returned : %i.\n", i));#endif OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "udp_plugin: message sent to %s on port %i\n", host, port)); osip_free (buf); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -