int read_packet(libgdbr_t *g) { struct parse_ctx ctx = {0}; int ret; if (!g) { eprintf ("Initialize libgdbr_t first\n"); return -1; } g->data_len = 0; while (r_socket_ready (g->sock, 0, READ_TIMEOUT) > 0) { int sz; sz = r_socket_read (g->sock, (void *)g->read_buff, g->read_max); if (sz <= 0) { eprintf ("%s: read failed\n", __func__); return -1; } ret = unpack (g, &ctx, sz); if (ret < 0) { eprintf ("%s: unpack failed\n", __func__); return -1; } if (!ret) { return 0; } } return -1; }
R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, int timeout) { int content_length = 0, xx, yy; int pxx = 1, first = 0; char buf[1500], *p, *q; RSocketHTTPRequest *hr = R_NEW0 (RSocketHTTPRequest); hr->s = r_socket_accept (s); if (!hr->s) { free (hr); return NULL; } if (timeout>0) r_socket_block_time (hr->s, 1, timeout); for (;;) { memset (buf, 0, sizeof (buf)); xx = r_socket_gets (hr->s, buf, sizeof (buf)); yy = r_socket_ready (hr->s, 0, 20); // eprintf ("READ %d (%s) READY %d\n", xx, buf, yy); if (!yy || (!xx && !pxx)) { break; } pxx = xx; if (first==0) { first = 1; if (strlen (buf)<3) { r_socket_http_close (hr); return NULL; } p = strchr (buf, ' '); if (p) *p = 0; hr->method = strdup (buf); if (p) { q = strstr (p+1, " HTTP"); //strchr (p+1, ' '); if (q) *q = 0; hr->path = strdup (p+1); } } else { if (!hr->agent && !strncmp (buf, "User-Agent: ", 12)) { hr->agent = strdup (buf+12); } else if (!hr->host && !strncmp (buf, "Host: ", 6)) { hr->host = strdup (buf+6); } else if (!strncmp (buf, "Content-Length: ", 16)) { content_length = atoi (buf+16); } } } if (content_length>0) { r_socket_read_block (hr->s, (ut8*)buf, 1); // one missing byte wtf hr->data = malloc (content_length+1); hr->data_length = content_length; r_socket_read_block (hr->s, hr->data, hr->data_length); hr->data[content_length] = 0; } return hr; }
R_API int r_socket_proc_ready (RSocketProc *sp, int secs, int usecs) { RSocket s; s.is_ssl = false; s.fd = sp->fd1[0]; return r_socket_ready (&s, secs, usecs); }
R_API bool r_socket_connect(RSocket *s, const char *host, const char *port, int proto, unsigned int timeout) { #if __WINDOWS__ struct sockaddr_in sa; struct hostent *he; WSADATA wsadata; TIMEVAL Timeout; Timeout.tv_sec = timeout; Timeout.tv_usec = 0; if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return false; } s->fd = socket (AF_INET, SOCK_STREAM, 0); #ifdef _MSC_VER if (s->fd == INVALID_SOCKET) { #else if (s->fd == -1) { #endif return false; } unsigned long iMode = 1; int iResult = ioctlsocket (s->fd, FIONBIO, &iMode); if (iResult != NO_ERROR) { eprintf ("ioctlsocket error: %d\n", iResult); } memset (&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname (host); if (he == (struct hostent*)0) { #ifdef _MSC_VER closesocket (s->fd); #else close (s->fd); #endif return false; } sa.sin_addr = *((struct in_addr *)he->h_addr); s->port = r_socket_port_by_name (port); sa.sin_port = htons (s->port); if (!connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) { #ifdef _MSC_VER closesocket (s->fd); #else close (s->fd); #endif return false; } iMode = 0; iResult = ioctlsocket (s->fd, FIONBIO, &iMode); if (iResult != NO_ERROR) { eprintf ("ioctlsocket error: %d\n", iResult); } if (timeout > 0) { r_socket_block_time (s, 1, timeout); } fd_set Write, Err; FD_ZERO (&Write); FD_ZERO (&Err); FD_SET (s->fd, &Write); FD_SET (s->fd, &Err); select (0, NULL, &Write, &Err, &Timeout); if (FD_ISSET (s->fd, &Write)) { return true; } return false; #elif __UNIX__ int ret; struct addrinfo hints = {0}; struct addrinfo *res, *rp; if (!proto) { proto = R_SOCKET_PROTO_TCP; } signal (SIGPIPE, SIG_IGN); if (proto == R_SOCKET_PROTO_UNIX) { if (!r_socket_unix_connect (s, host)) { return false; } } else { hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_protocol = proto; int gai = getaddrinfo (host, port, &hints, &res); if (gai != 0) { eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai)); return false; } for (rp = res; rp != NULL; rp = rp->ai_next) { int flag = 1; s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s->fd == -1) { perror ("socket"); continue; } ret = setsockopt (s->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof (flag)); if (ret < 0) { perror ("setsockopt"); close (s->fd); s->fd = -1; continue; } if (timeout > 0) { r_socket_block_time (s, 1, timeout); //fcntl (s->fd, F_SETFL, O_NONBLOCK, 1); } ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen); if (timeout == 0 && ret == 0) { freeaddrinfo (res); return true; } if (ret == 0 /* || nonblocking */) { struct timeval tv; fd_set fdset, errset; FD_ZERO (&fdset); FD_SET (s->fd, &fdset); tv.tv_sec = 1; //timeout; tv.tv_usec = 0; if (r_socket_is_connected (s)) { freeaddrinfo (res); return true; } if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) { int so_error; socklen_t len = sizeof so_error; ret = getsockopt (s->fd, SOL_SOCKET, SO_ERROR, &so_error, &len); if (ret == 0 && so_error == 0) { //fcntl (s->fd, F_SETFL, O_NONBLOCK, 0); //r_socket_block_time (s, 0, 0); freeaddrinfo (res); return true; } } } close (s->fd); s->fd = -1; } freeaddrinfo (res); if (!rp) { eprintf ("Could not resolve address '%s' or failed to connect\n", host); return false; } } #endif #if HAVE_LIB_SSL if (s->is_ssl) { s->ctx = SSL_CTX_new (SSLv23_client_method ()); if (!s->ctx) { r_socket_free (s); return false; } s->sfd = SSL_new (s->ctx); SSL_set_fd (s->sfd, s->fd); if (SSL_connect (s->sfd) != 1) { r_socket_free (s); return false; } } #endif return true; } /* close the file descriptor associated with the RSocket s */ R_API int r_socket_close_fd(RSocket *s) { #ifdef _MSC_VER return s->fd != INVALID_SOCKET ? closesocket (s->fd) : false; #else return s->fd != -1 ? close (s->fd) : false; #endif } /* shutdown the socket and close the file descriptor */ R_API int r_socket_close(RSocket *s) { int ret = false; if (!s) { return false; } if (s->fd != -1) { #if __UNIX__ shutdown (s->fd, SHUT_RDWR); #endif #if __WINDOWS__ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms740481(v=vs.85).aspx shutdown (s->fd, SD_SEND); if (r_socket_ready (s, 0, 250)) { do { char buf = 0; ret = recv (s->fd, &buf, 1, 0); } while (ret != 0 && ret != SOCKET_ERROR); } ret = closesocket (s->fd); #else ret = close (s->fd); #endif } #if HAVE_LIB_SSL if (s->is_ssl && s->sfd) { SSL_free (s->sfd); s->sfd = NULL; } #endif return ret; }