00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00030 #ifndef DISABLE_SOCKET
00031 #ifndef _WIN32
00032
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <stdbool.h>
00036 #include <string.h>
00037 #include <stdarg.h>
00038 #include <netdb.h>
00039 #include <fcntl.h>
00040 #include <unistd.h>
00041 #include <poll.h>
00042 #include <arpa/inet.h>
00043 #include <netinet/in.h>
00044 #include <sys/socket.h>
00045 #include <sys/time.h>
00046 #include <sys/stat.h>
00047 #include "qDecoder.h"
00048 #include "qInternal.h"
00049
00050 #if defined(ENABLE_SENDFILE) && defined(__linux__)
00051 #include <sys/sendfile.h>
00052 #define MAX_SENDFILE_CHUNK_SIZE (1 * 1024 * 1024 * 1024)
00053 #else
00054 #define MAX_SENDFILE_CHUNK_SIZE (64 * 1024)
00055 #endif
00056 #define MAX_SAVEINTOFILE_CHUNK_SIZE (64 * 1024)
00057
00058 static bool _getAddr(struct sockaddr_in *addr, const char *hostname, int port);
00059
00074 int qSocketOpen(const char *hostname, int port) {
00075
00076 struct sockaddr_in addr;
00077 if (_getAddr(&addr, hostname, port) == false) return -1;
00078
00079
00080 int sockfd;
00081 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -2;
00082
00083
00084 if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
00085 qSocketClose(sockfd);
00086 return -3;
00087 }
00088
00089 return sockfd;
00090 }
00091
00105 bool qSocketClose(int sockfd) {
00106 if(close(sockfd) == 0) return true;
00107 return false;
00108 }
00109
00124 int qSocketWaitReadable(int sockfd, int timeoutms) {
00125 struct pollfd fds[1];
00126
00127 fds[0].fd = sockfd;
00128 fds[0].events = POLLIN;
00129
00130 int status = poll(fds, 1, timeoutms);
00131 if(status <= 0) return status;
00132
00133 if(fds[0].revents & POLLIN) return 1;
00134 return -1;
00135 }
00136
00151 int qSocketWaitWritable(int sockfd, int timeoutms) {
00152 struct pollfd fds[1];
00153
00154 fds[0].fd = sockfd;
00155 fds[0].events = POLLOUT;
00156
00157 int status = poll(fds, 1, timeoutms);
00158 if(status <= 0) return status;
00159
00160 if(fds[0].revents & POLLOUT) return 1;
00161 return -1;
00162 }
00163
00180 ssize_t qSocketRead(void *binary, int sockfd, size_t nbytes, int timeoutms) {
00181 if(nbytes == 0) return 0;
00182
00183 ssize_t readbytes = 0;
00184 int sockstatus = 0;
00185 while(readbytes < nbytes) {
00186 sockstatus = qSocketWaitReadable(sockfd, timeoutms);
00187 if(sockstatus <= 0) break;
00188
00189 ssize_t readsize = read(sockfd, binary+readbytes, nbytes-readbytes);
00190 if(readsize <= 0) {
00191 sockstatus = -1;
00192 break;
00193 }
00194 readbytes += readsize;
00195 }
00196
00197 if(readbytes > 0) return readbytes;
00198 return sockstatus;
00199 }
00200
00220 ssize_t qSocketGets(char *str, int sockfd, size_t nbytes, int timeoutms) {
00221 char *ptr;
00222 ssize_t readcnt = 0;
00223 for (ptr = str; readcnt < (nbytes - 1); ptr++) {
00224 int sockstatus = qSocketWaitReadable(sockfd, timeoutms);
00225 if (sockstatus <= 0) {
00226 *ptr = '\0';
00227 return sockstatus;
00228 }
00229
00230 if (read(sockfd, ptr, 1) != 1) {
00231 if (ptr == str) return -1;
00232 break;
00233 }
00234
00235 readcnt++;
00236 if (*ptr == '\n') break;
00237 if (*ptr == '\r') ptr--;
00238 }
00239
00240 *ptr = '\0';
00241 return readcnt;
00242 }
00243
00258 ssize_t qSocketWrite(int sockfd, const void *binary, size_t nbytes) {
00259 return _q_write(sockfd, binary, nbytes);
00260 }
00261
00275 ssize_t qSocketPuts(int sockfd, const char *str) {
00276 char *buf = (char *)malloc(strlen(str) + 2 + 1);
00277 if(buf == NULL) return -1;
00278 sprintf(buf, "%s\r\n", str);
00279
00280 ssize_t sent = _q_write(sockfd, buf, strlen(buf));
00281 free(buf);
00282
00283 return sent;
00284 }
00285
00301 ssize_t qSocketPrintf(int sockfd, const char *format, ...) {
00302 char buf[MAX_LINEBUF];
00303 va_list arglist;
00304
00305 va_start(arglist, format);
00306 vsnprintf(buf, sizeof(buf), format, arglist);
00307 va_end(arglist);
00308
00309 return _q_write(sockfd, buf, strlen(buf));
00310 }
00311
00327 off_t qSocketSendfile(int sockfd, int fd, off_t offset, off_t nbytes) {
00328 struct stat filestat;
00329 if (fstat(fd, &filestat) < 0) return -1;
00330
00331 off_t sent = 0;
00332 off_t rangesize = filestat.st_size - offset;
00333 if(rangesize < 0) rangesize = 0;
00334 else if(nbytes > 0 && nbytes < rangesize) rangesize = nbytes;
00335
00336 #if !(defined(ENABLE_SENDFILE) && defined(__linux__))
00337 if (offset > 0) lseek(fd, offset, SEEK_SET);
00338 #endif
00339
00340 while(sent < rangesize) {
00341 size_t sendsize;
00342 if(rangesize - sent <= MAX_SENDFILE_CHUNK_SIZE) sendsize = rangesize - sent;
00343 else sendsize = MAX_SENDFILE_CHUNK_SIZE;
00344
00345 ssize_t ret = 0;
00346 #if defined(ENABLE_SENDFILE) && defined(__linux__)
00347 ret = sendfile(sockfd, fd, &offset, sendsize);
00348 #else
00349 ret = qFileSend(sockfd, fd, sendsize);
00350 #endif
00351 if(ret <= 0) break;
00352 sent += ret;
00353 }
00354
00355 return sent;
00356 }
00357
00377 off_t qSocketSaveIntoFile(int fd, int sockfd, off_t nbytes, int timeoutms) {
00378 if(nbytes <= 0) return 0;
00379
00380 off_t readbytes, readed;
00381 for (readbytes = 0; readbytes < nbytes; readbytes += readed) {
00382
00383 int readsize;
00384 if (nbytes - readbytes < MAX_SAVEINTOFILE_CHUNK_SIZE) readsize = nbytes - readbytes;
00385 else readsize = MAX_SAVEINTOFILE_CHUNK_SIZE;
00386
00387
00388 if (qSocketWaitReadable(sockfd, timeoutms) <= 0) {
00389 if(readbytes == 0) return -1;
00390 break;
00391 }
00392
00393 readed = qFileSend(fd, sockfd, readsize);
00394 if (readed <= 0) {
00395 if(readbytes == 0) return -1;
00396 break;
00397 }
00398 }
00399 return readbytes;
00400 }
00401
00420 ssize_t qSocketSaveIntoMemory(char *mem, int sockfd, size_t nbytes, int timeoutms) {
00421 if(nbytes <= 0) return 0;
00422
00423 char *mp;
00424 ssize_t readbytes, readed;
00425 for (readbytes = 0, mp = mem; readbytes < nbytes; readbytes += readed, mp += readed) {
00426
00427 size_t readsize = nbytes - readbytes;
00428
00429
00430 if (qSocketWaitReadable(sockfd, timeoutms) <= 0) {
00431 if(readbytes == 0) return -1;
00432 break;
00433 }
00434
00435
00436 readed = read(sockfd, mp, readsize);
00437 if (readed <= 0) {
00438 if(readbytes == 0) return -1;
00439 break;
00440 }
00441 }
00442
00443 return readbytes;
00444 }
00445
00457 static bool _getAddr(struct sockaddr_in *addr, const char *hostname, int port) {
00458
00459 memset((void*)addr, 0, sizeof(struct sockaddr_in));
00460 if (!inet_aton(hostname, &addr->sin_addr)) {
00461 struct hostent *hp;
00462 if ((hp = gethostbyname (hostname)) == 0) return false;
00463 memcpy (&addr->sin_addr, hp->h_addr, sizeof(struct in_addr));
00464 }
00465 addr->sin_family = AF_INET;
00466 addr->sin_port = htons(port);
00467
00468 return true;
00469 }
00470
00471 #endif
00472 #endif