title: call linux socket function sendto:error,operation not permitted
body: <p>Environment:
  <br>PC sys:windows xp
  <br>jdk:1.6
  <br>ndk:android-ndk-r9b
  <br>compile env:MinGW</p>
  
  <p>Descrpiton:
  <br>I'm developing a sip endpoint app, which is based on the opensource sip stack "doubango", in Android device. The socket functions are called using NDK but not directly JAVA. When normally use, it's OK. Then clean the device's memory using some software, or stop Service manully, and make it exit abnormally. Seems that it stops without call function close(socket). Next time when I use, it will throw error calling socket function :sendto(),the errno=1 which means "operation not permitted".
  <br>I've added "uses-permission android:name="android.permission.INTERNET""
  <br>Does anyone can give me a hand?</p>
  
  <p>PS:I test in devices without ROOT permission, and this issue will happen. But I test a device with ROOT permission, it doesn't happen. Does it matter?</p>
  
  <hr>
  
  <p>Job Is Done. There are sth mistakes i made in the Java layer. Some parameters i set in Sip stack are wrong. </p>
  
  <hr>
  
  <p><br></p>
  
  <p><br>Here follows the code segment:
  <br></p>
  
  <pre><code>int tnet_sockfd_sendto(tnet_fd_t fd, const struct sockaddr *to, const void* buf,     tsk_size_t size)
  {
  tsk_size_t sent = 0;
  int ret = -1;
  
  if(fd == TNET_INVALID_FD){
      TSK_DEBUG_ERROR("Using invalid FD to send data.");
      goto bail;
  }
  if(!buf || !size){
      TSK_DEBUG_ERROR("Using invalid BUFFER.");
      ret = -2;
      goto bail;
  }
  
  while(sent &lt; size){
      int try_guard = 10;
  #if TNET_UNDER_WINDOWS
      WSABUF wsaBuffer;
      DWORD numberOfBytesSent = 0;
      wsaBuffer.buf = ((CHAR*)buf) + sent;
      wsaBuffer.len = (size - sent);
  try_again:
      ret = WSASendTo(fd, &amp;wsaBuffer, 1, &amp;numberOfBytesSent, 0, to, tnet_get_sockaddr_size(to), 0, 0); // returns zero if succeed
      if(ret == 0){
          ret = numberOfBytesSent;
      }
  #else
  try_again:
      ret = sendto(fd, (((const uint8_t*)buf)+sent), (size-sent), 0, to, tnet_get_sockaddr_size(to)); // returns number of sent bytes if succeed
  #endif
      if(ret &lt;= 0){
          if(tnet_geterrno() == TNET_ERROR_WOULDBLOCK){
              TSK_DEBUG_INFO("SendUdp() - WouldBlock. Retrying...");
              if(try_guard--){
                  tsk_thread_sleep(10);
                  goto try_again;
              }
          }
          else{
                                  ***/* Just throw error here*/***
              TSK_DEBUG_INFO("errno: %d",tnet_geterrno());
              TNET_PRINT_LAST_ERROR("sendto() failed");
  
          }
          goto bail;
      }
      else{
          sent += ret;
      }
  }
  
  bail:
  return (size == sent) ? sent : ret;
  }
  </code></pre>
  
  <p><br></p>
  
  <pre><code>#define tnet_soccket(family, type, protocol) socket((family), (type), (protocol))
  </code></pre>
  
  <p><br></p>
  
  <pre><code>tnet_socket_t* tnet_socket_create_2(const char* host, tnet_port_t port_,tnet_socket_type_t type, tsk_bool_t nonblocking, tsk_bool_t bindsocket)
  {
  tnet_socket_t *sock;
  
  if((sock = tsk_object_new(tnet_socket_def_t))){
      int status;
      tsk_istr_t port;
      struct addrinfo *result = tsk_null;
      struct addrinfo *ptr = tsk_null;
      struct addrinfo hints;
      tnet_host_t local_hostname;
  
      sock-&gt;port = port_;
      tsk_itoa(sock-&gt;port, &amp;port);
      sock-&gt;type = type;
  
      memset(local_hostname, 0, sizeof(local_hostname));
  
      /* Get the local host name */
      if(host != TNET_SOCKET_HOST_ANY &amp;&amp; !tsk_strempty(host)){
          memcpy(local_hostname, host, tsk_strlen(host)&gt;sizeof(local_hostname)-1 ? sizeof(local_hostname)-1 : tsk_strlen(host));
      }
      else{
          if(TNET_SOCKET_TYPE_IS_IPV6(sock-&gt;type)){
              memcpy(local_hostname, "::", 2);
          }
          else{
              memcpy(local_hostname, "0.0.0.0", 7);
          }
      }
  
  
      TSK_DEBUG_INFO("local_hostname: %s",local_hostname);
  
      /* hints address info structure */
      memset(&amp;hints, 0, sizeof(hints));
      hints.ai_family = TNET_SOCKET_TYPE_IS_IPV46(sock-&gt;type) ? AF_UNSPEC : (TNET_SOCKET_TYPE_IS_IPV6(sock-&gt;type) ? AF_INET6 : AF_INET);
      hints.ai_socktype = TNET_SOCKET_TYPE_IS_STREAM(sock-&gt;type) ? SOCK_STREAM : SOCK_DGRAM;
      hints.ai_protocol = TNET_SOCKET_TYPE_IS_STREAM(sock-&gt;type) ? IPPROTO_TCP : IPPROTO_UDP;
      hints.ai_flags = AI_PASSIVE
  #if !TNET_UNDER_WINDOWS || _WIN32_WINNT&gt;=0x600
          | AI_ADDRCONFIG
  #endif
          ;
  
      /* Performs getaddrinfo */
      if((status = tnet_getaddrinfo(local_hostname, port, &amp;hints, &amp;result))){
          TNET_PRINT_LAST_ERROR("tnet_getaddrinfo(family=%d, hostname=%s and port=%s) failed: [%s]", 
              hints.ai_family, local_hostname, port, tnet_gai_strerror(status));
          goto bail;
      }
  
      /* Find our address. */
      for(ptr = result; ptr; ptr = ptr-&gt;ai_next){
          sock-&gt;fd = tnet_soccket(ptr-&gt;ai_family, ptr-&gt;ai_socktype, ptr-&gt;ai_protocol);
          if(ptr-&gt;ai_family != AF_INET6 &amp;&amp; ptr-&gt;ai_family != AF_INET){
              continue;
          }
          /* To avoid "Address already in use" error
          * Check issue 368 (https://code.google.com/p/doubango/issues/detail?id=368) to understand why it's not used for UDP/DTLS.
          */
          //
          if (TNET_SOCKET_TYPE_IS_STREAM(sock-&gt;type)) {
              TSK_DEBUG_INFO("Socket Type: Stream");
              if ((status = tnet_sockfd_reuseaddr(sock-&gt;fd, 1))) {
                  // do not break...continue
              }
          }
  
  
          if(bindsocket){
              /* Bind the socket */
  
              if((status = bind(sock-&gt;fd, ptr-&gt;ai_addr, ptr-&gt;ai_addrlen))){
                  TNET_PRINT_LAST_ERROR("bind to [%s:%s]have failed", local_hostname, port);
                  tnet_socket_close(sock);
                  continue;
              }
  
              /* Get local IP string. */
              if((status = tnet_get_ip_n_port(sock-&gt;fd , tsk_true/*local*/, &amp;sock-&gt;ip, &amp;sock-&gt;port))) /* % */
              //if((status = tnet_getnameinfo(ptr-&gt;ai_addr, ptr-&gt;ai_addrlen, sock-&gt;ip, sizeof(sock-&gt;ip), 0, 0, NI_NUMERICHOST)))
              {
                  TNET_PRINT_LAST_ERROR("Failed to get local IP and port.");
                  tnet_socket_close(sock);
                  continue;
              }
          }
  
          /* sets the real socket type (if ipv46) */
          if(ptr-&gt;ai_family == AF_INET6) {
              TNET_SOCKET_TYPE_SET_IPV6Only(sock-&gt;type);
          }
          else{
              TNET_SOCKET_TYPE_SET_IPV4Only(sock-&gt;type);
          }
          break;
      }
  
      /* Check socket validity. */
      if(!TNET_SOCKET_IS_VALID(sock)) {
          TNET_PRINT_LAST_ERROR("Invalid socket.");
          goto bail;
      }
  
  #if TNET_UNDER_IPHONE || TNET_UNDER_IPHONE_SIMULATOR
      /* disable SIGPIPE signal */
      {
          int yes = 1;
          if(setsockopt(sock-&gt;fd, SOL_SOCKET, SO_NOSIGPIPE, (char*)&amp;yes, sizeof(int))){
              TNET_PRINT_LAST_ERROR("setsockopt(SO_NOSIGPIPE) have failed.");
          }
      }
  #endif /* TNET_UNDER_IPHONE */
  
      /* Sets the socket to nonblocking mode */
      if(nonblocking){
          if((status = tnet_sockfd_set_nonblocking(sock-&gt;fd))){
              goto bail;
          }
      }
  
  bail:
      /* Free addrinfo */
      tnet_freeaddrinfo(result);
  
      /* Close socket if failed. */
      if(status){
          if(TNET_SOCKET_IS_VALID(sock)){
              tnet_socket_close(sock);
          }
          return tsk_null;
      }
  }
  
  return sock;
  }
  </code></pre>
  
  <p><br></p>
  
  <pre><code>int tnet_sockfd_reuseaddr(tnet_fd_t fd, int reuseAddr)
  {
  if (fd != TNET_INVALID_FD) {
      int ret;
      #if defined(SOLARIS)
          static const char yes = '1';
          static const char no = '0';
      #else
          static const int yes = 1;
          static const int no = 0;
      #endif
          if ((ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)(reuseAddr ? &amp;yes : &amp;no), sizeof(int)))) {
              TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEADDR, fd=%d) have failed", fd);
              return ret;
          }
  //      #if defined(SO_REUSEPORT)
          if ((ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)(reuseAddr ? &amp;yes : &amp;no), sizeof(int)))) {
              TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEPORT, fd=%d) have failed", fd);
              return ret;
          }
  //      #endif
      return 0;
  }
  return -1;
  }
  </code></pre>
  
  <p><br></p>
  
  <pre><code>#define tnet_sockfd_set_nonblocking(fd) tnet_sockfd_set_mode(fd, 1)
  int tnet_sockfd_set_mode(tnet_fd_t fd, int nonBlocking)
  {
  if(fd != TNET_INVALID_FD)
  {
  #if TNET_UNDER_WINDOWS
  ULONG mode = nonBlocking;
  if(ioctlsocket(fd, FIONBIO, &amp;mode))
  //if(WSAIoctl(fd, FIONBIO, &amp;nonblocking, sizeof(nonblocking), NULL, 0, NULL, NULL, NULL) == SOCKET_ERROR)
  {
      TNET_PRINT_LAST_ERROR("ioctlsocket(FIONBIO) have failed.");
      return -1;
  }
  #else
  int flags;
  if((flags = fcntl(fd, F_GETFL, 0)) &lt; 0) { 
      TNET_PRINT_LAST_ERROR("fcntl(F_GETFL) have failed.");
      return -1;
  } 
  if(fcntl(fd, F_SETFL, flags | (nonBlocking ? O_NONBLOCK : ~O_NONBLOCK)) &lt; 0){ 
      TNET_PRINT_LAST_ERROR("fcntl(O_NONBLOCK/O_NONBLOCK) have failed.");
      return -1;
  } 
  #endif
  
  // int on = 1;
  // ioctl(fd, FIONBIO, (char *)&amp;on);
  
  }
  return 0;
  }
  </code></pre>
  
  <p><br></p>