/* * Create new socket/endpoint for communication and returns a descriptor. */ PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto, pj_sock_t *sock) { PJ_CHECK_STACK(); /* Sanity checks. */ PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL); PJ_ASSERT_RETURN(PJ_INVALID_SOCKET==-1, (*sock=PJ_INVALID_SOCKET, PJ_EINVAL)); *sock = socket(af, type, proto); if (*sock == PJ_INVALID_SOCKET) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else { pj_int32_t val = 1; if (type == pj_SOCK_STREAM()) { pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), pj_SO_NOSIGPIPE(), &val, sizeof(val)); } #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 if (type == pj_SOCK_DGRAM()) { pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), SO_NOSIGPIPE, &val, sizeof(val)); } #endif return PJ_SUCCESS; } }
/* * Accept incoming connections */ PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd, pj_sock_t *newsock, pj_sockaddr_t *addr, int *addrlen) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(newsock != NULL, PJ_EINVAL); #if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0 if (addr) { PJ_SOCKADDR_SET_LEN(addr, *addrlen); } #endif *newsock = accept(serverfd, (struct sockaddr*)addr, (socklen_t*)addrlen); if (*newsock==PJ_INVALID_SOCKET) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else { #if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0 if (addr) { PJ_SOCKADDR_RESET_LEN(addr); } #endif return PJ_SUCCESS; } }
PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock, int how) { PJ_CHECK_STACK(); if (shutdown(sock, how) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Start listening to incoming connections. */ PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock, int backlog) { PJ_CHECK_STACK(); if (listen(sock, backlog) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Connect socket. */ PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock, const pj_sockaddr_t *addr, int namelen) { PJ_CHECK_STACK(); if (connect(sock, (struct sockaddr*)addr, namelen) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Get socket name. */ PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock, pj_sockaddr_t *addr, int *namelen) { PJ_CHECK_STACK(); if (getsockname(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else { PJ_SOCKADDR_RESET_LEN(addr); return PJ_SUCCESS; } }
/* * Set socket option. */ PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock, pj_uint16_t level, pj_uint16_t optname, const void *optval, int optlen) { PJ_CHECK_STACK(); if (setsockopt(sock, level, optname, (const char*)optval, optlen) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Get socket option. */ PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock, pj_uint16_t level, pj_uint16_t optname, void *optval, int *optlen) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(optval && optlen, PJ_EINVAL); if (getsockopt(sock, level, optname, (char*)optval, (socklen_t*)optlen)!=0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Receive data. */ PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock, void *buf, pj_ssize_t *len, unsigned flags) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(buf && len, PJ_EINVAL); *len = recv(sock, (char*)buf, *len, flags); if (*len < 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Bind socket. */ PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock, const pj_sockaddr_t *addr, int len) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(addr && len >= (int)sizeof(struct sockaddr_in), PJ_EINVAL); CHECK_ADDR_LEN(addr, len); if (bind(sock, (struct sockaddr*)addr, len) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Close socket. */ PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock) { int rc; PJ_CHECK_STACK(); #if defined(PJ_WIN32) && PJ_WIN32!=0 || \ defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0 rc = closesocket(sock); #else rc = close(sock); #endif if (rc != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Create new socket/endpoint for communication and returns a descriptor. */ PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto, pj_sock_t *sock) { PJ_CHECK_STACK(); /* Sanity checks. */ PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL); PJ_ASSERT_RETURN((unsigned)PJ_INVALID_SOCKET==INVALID_SOCKET, (*sock=PJ_INVALID_SOCKET, PJ_EINVAL)); *sock = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED); if (*sock == PJ_INVALID_SOCKET) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); #if PJ_SOCK_DISABLE_WSAECONNRESET && \ (!defined(PJ_WIN32_WINCE) || PJ_WIN32_WINCE==0) #ifndef SIO_UDP_CONNRESET #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) #endif /* Disable WSAECONNRESET for UDP. * See https://trac.pjsip.org/repos/ticket/1197 */ if (type==PJ_SOCK_DGRAM) { DWORD dwBytesReturned = 0; BOOL bNewBehavior = FALSE; DWORD rc; rc = WSAIoctl(*sock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL); if (rc==SOCKET_ERROR) { // Ignored.. } } #endif return PJ_SUCCESS; }
/* * Create new socket/endpoint for communication and returns a descriptor. */ PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto, pj_sock_t *sock) { PJ_CHECK_STACK(); /* Sanity checks. */ PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL); PJ_ASSERT_RETURN(PJ_INVALID_SOCKET==-1, (*sock=PJ_INVALID_SOCKET, PJ_EINVAL)); *sock = socket(af, type, proto); if (*sock == PJ_INVALID_SOCKET) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Bind socket. */ PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock, const pj_sockaddr_t *addr, int len) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(addr && len >= (int)sizeof(struct sockaddr_in), PJ_EINVAL); CHECK_ADDR_LEN(addr, len); pj_int32_t val = 1; int rc = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &val, sizeof(val)); if (rc != 0) return rc; if (bind(sock, (struct sockaddr*)addr, len) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Send data */ PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock, const void *buf, pj_ssize_t *len, unsigned flags) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(len, PJ_EINVAL); #ifdef MSG_NOSIGNAL /* Suppress SIGPIPE. See https://trac.pjsip.org/repos/ticket/1538 */ flags |= MSG_NOSIGNAL; #endif *len = send(sock, (const char*)buf, *len, flags); if (*len < 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Send data. */ PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock, const void *buf, pj_ssize_t *len, unsigned flags, const pj_sockaddr_t *to, int tolen) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(len, PJ_EINVAL); CHECK_ADDR_LEN(to, tolen); *len = sendto(sock, (const char*)buf, *len, flags, (const struct sockaddr*)to, tolen); if (*len < 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Receive data. */ PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock, void *buf, pj_ssize_t *len, unsigned flags, pj_sockaddr_t *from, int *fromlen) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(buf && len, PJ_EINVAL); PJ_ASSERT_RETURN(from && fromlen, (*len=-1, PJ_EINVAL)); *len = recvfrom(sock, (char*)buf, *len, flags, (struct sockaddr*)from, (socklen_t*)fromlen); if (*len < 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else { PJ_SOCKADDR_RESET_LEN(from); return PJ_SUCCESS; } }
/* * Set socket option. */ PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock, pj_uint16_t level, pj_uint16_t optname, const void *optval, int optlen) { int status; PJ_CHECK_STACK(); #if (defined(PJ_WIN32) && PJ_WIN32) || (defined(PJ_SUNOS) && PJ_SUNOS) /* Some opt may still need int value (e.g:SO_EXCLUSIVEADDRUSE in win32). */ status = setsockopt(sock, level, ((optname&0xff00)==0xff00)?(int)optname|0xffff0000:optname, (const char*)optval, optlen); #else status = setsockopt(sock, level, optname, (const char*)optval, optlen); #endif if (status != 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else return PJ_SUCCESS; }
/* * Create new socket/endpoint for communication and returns a descriptor. */ PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto, pj_sock_t *sock) { PJ_CHECK_STACK(); /* Sanity checks. */ PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL); PJ_ASSERT_RETURN((unsigned)PJ_INVALID_SOCKET==INVALID_SOCKET, (*sock=PJ_INVALID_SOCKET, PJ_EINVAL)); *sock = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED); if (*sock == PJ_INVALID_SOCKET) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); #if PJ_SOCK_DISABLE_WSAECONNRESET && \ (!defined(PJ_WIN32_WINCE) || PJ_WIN32_WINCE==0) #ifndef SIO_UDP_CONNRESET #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) #endif /* Disable WSAECONNRESET for UDP. * See https://trac.pjsip.org/repos/ticket/1197 */ if (type==PJ_SOCK_DGRAM) { DWORD dwBytesReturned = 0; BOOL bNewBehavior = FALSE; DWORD rc; int iOptVal; int retOpt; int iOptLen; int iOptValRet = 0; iOptLen = sizeof(int); // POPOV: for debug //retOpt = getsockopt(*sock, SOL_SOCKET, SO_SNDBUF, (char*)&iOptValRet, &iOptLen); //retOpt = getsockopt(*sock, SOL_SOCKET, SO_RCVBUF, (char*)&iOptValRet, &iOptLen); // POPOV: setting socket buffers //iOptVal = 2097152; iOptVal = 65536; retOpt = setsockopt(*sock, SOL_SOCKET, PJ_SO_SNDBUF, (char*)&iOptVal, iOptLen); retOpt = setsockopt(*sock, SOL_SOCKET, PJ_SO_RCVBUF, (char*)&iOptVal, iOptLen); // POPOV: for debug //retOpt = getsockopt(*sock, SOL_SOCKET, SO_SNDBUF, (char*)&iOptValRet, &iOptLen); //retOpt = getsockopt(*sock, SOL_SOCKET, SO_RCVBUF, (char*)&iOptValRet, &iOptLen); rc = WSAIoctl(*sock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL); if (rc==SOCKET_ERROR) { // Ignored.. } } #endif return PJ_SUCCESS; }