// tries to read exactly one line, until '\n', then overwrites the \n with \0 // bytesread contains the number of bytes read till \n was encountered // (so 0 in case \n was the first char). // returns RS_E_OUT_OF_BUFFER if the line doesnt fit into the buffer. int rocksock_readline(rocksock* sock, char* buffer, size_t bufsize, size_t* bytesread) { // TODO: make more efficient by peeking into the buffer (Flag MSG_PEEK to recv), instead of reading byte by byte // would need a different approach for ssl though. if (!sock) return RS_E_NULL; if (!buffer || !bufsize || !bytesread) return rocksock_seterror(sock, RS_ET_OWN, RS_E_NULL, ROCKSOCK_FILENAME, __LINE__); char* ptr = buffer; size_t bytesread2 = 0; int ret; *bytesread = 0; while(*bytesread < bufsize) { ret = rocksock_recv(sock, ptr, 1, 1, &bytesread2); if(ret || !bytesread2) return ret; *bytesread += bytesread2; if(ptr > buffer + bufsize) break; if(*bytesread > bufsize) { *bytesread = bufsize; break; } if(*ptr == '\n') { *ptr = 0; *bytesread -= 1; return 0; } ptr++; } return rocksock_seterror(sock, RS_ET_OWN, RS_E_OUT_OF_BUFFER, ROCKSOCK_FILENAME, __LINE__); }
int rocksock_ssl_peek(rocksock* sock, int *result) { char buf[4]; int ret; ret = SSL_peek(sock->ssl, buf, 1); if(ret >= 0) *result = 1; else { ret = SSL_get_error(sock->ssl, ret); if(ret == SSL_ERROR_WANT_READ) return rocksock_seterror(sock, RS_ET_OWN, RS_E_HIT_READTIMEOUT, ROCKSOCK_FILENAME, __LINE__); return rocksock_seterror(sock, RS_ET_SSL, ret, ROCKSOCK_FILENAME, __LINE__); } return rocksock_seterror(sock, RS_ET_OWN, 0, NULL, 0); }
int rocksock_ssl_connect_fd(rocksock* sock) { sock->sslctx = SSL_CTX_new(SSLv23_client_method()); if (!sock->sslctx) { ERR_print_errors_fp(stderr); return rocksock_seterror(sock, RS_ET_OWN, RS_E_SSL_GENERIC, ROCKSOCK_FILENAME, __LINE__); } sock->ssl = SSL_new(sock->sslctx); if (!sock->ssl) { ERR_print_errors_fp(stderr); return rocksock_seterror(sock, RS_ET_OWN, RS_E_SSL_GENERIC, ROCKSOCK_FILENAME, __LINE__); } SSL_set_fd(sock->ssl, sock->socket); int ret = SSL_connect(sock->ssl); if(ret != 1) { if((ret = SSL_get_error(sock->ssl, ret)) == SSL_ERROR_WANT_READ) return rocksock_seterror(sock, RS_ET_OWN, RS_E_HIT_CONNECTTIMEOUT, ROCKSOCK_FILENAME, __LINE__); //ERR_print_errors_fp(stderr); //printf("%dxxx\n", SSL_get_error(sock->ssl, ret)); return rocksock_seterror(sock, RS_ET_SSL, ret, ROCKSOCK_FILENAME, __LINE__); } return 0; }
int rocksock_add_proxy(rocksock* sock, rs_proxyType proxytype, const char* host, unsigned short port, const char* username, const char* password) { rs_proxy* prx; if (!sock) return RS_E_NULL; if(!host) return rocksock_seterror(sock, RS_ET_OWN, RS_E_NULL, ROCKSOCK_FILENAME, __LINE__); if(proxytype == RS_PT_SOCKS4 && (username || password)) return rocksock_seterror(sock, RS_ET_OWN, RS_E_SOCKS4_NOAUTH, ROCKSOCK_FILENAME, __LINE__); if(proxytype == RS_PT_SOCKS5 && ((username && strlen(username) > 255) || (password && strlen(password) > 255))) return rocksock_seterror(sock, RS_ET_OWN, RS_E_SOCKS5_AUTH_EXCEEDSIZE, ROCKSOCK_FILENAME, __LINE__); if(!sock->proxies) return rocksock_seterror(sock, RS_ET_OWN, RS_E_NO_PROXYSTORAGE, ROCKSOCK_FILENAME, __LINE__); size_t l = strlen(host); if(l > 255) return rocksock_seterror(sock, RS_ET_OWN, RS_E_HOSTNAME_TOO_LONG, ROCKSOCK_FILENAME, __LINE__); sock->lastproxy++; prx = &sock->proxies[sock->lastproxy]; prx->hostinfo.port = port; prx->proxytype = proxytype; memcpy(prx->hostinfo.host, host, l+1); memcpy(prx->username, username?username:"", username?strlen(username)+1:1); memcpy(prx->password, password?password:"", password?strlen(password)+1:1); return rocksock_seterror(sock, RS_ET_OWN, 0, NULL, 0); }