38 #include <sys/types.h>
42 #include <arpa/inet.h>
43 #include <sys/socket.h>
60 static int socket_wait(
int fd,
int is_read)
62 fd_set fds, *fdr = 0, *fdw = 0;
65 tv.tv_sec = 5; tv.tv_usec = 0;
68 if (is_read) fdr = &fds;
70 ret =
select(fd+1, fdr, fdw, 0, &tv);
72 if (ret == -1) perror(
"select");
75 fprintf(stderr,
"select time-out\n");
76 else if (ret == SOCKET_ERROR)
77 fprintf(stderr,
"select: %d\n", WSAGetLastError());
86 static int socket_connect(
const char *host,
const char *port)
88 #define __err_connect(func) do { perror(func); freeaddrinfo(res); return -1; } while (0)
91 struct linger lng = { 0, 0 };
92 struct addrinfo hints, *res = 0;
93 memset(&hints, 0,
sizeof(
struct addrinfo));
94 hints.ai_family = AF_UNSPEC;
95 hints.ai_socktype = SOCK_STREAM;
98 if (getaddrinfo(host, port, &hints, &res) != 0)
__err_connect(
"getaddrinfo");
99 if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1)
__err_connect(
"socket");
103 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) == -1)
__err_connect(
"setsockopt");
104 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lng,
sizeof(lng)) == -1)
__err_connect(
"setsockopt");
105 if (connect(fd, res->ai_addr, res->ai_addrlen) != 0)
__err_connect(
"connect");
111 char *int64tostr(
char *buf,
int64_t x)
116 buf[i++] =
'0' + x % 10;
120 for (cnt = i, i = 0; i < cnt/2; ++i) {
121 int c = buf[i]; buf[i] = buf[cnt-i-1]; buf[cnt-i-1] = c;
126 int64_t strtoint64(
const char *buf)
129 for (x = 0; *buf !=
'\0'; ++buf)
130 x = x * 10 + ((
int64_t) *buf - 48);
134 int knet_win32_init()
137 return WSAStartup(MAKEWORD(2, 2), &wsaData);
139 void knet_win32_destroy()
147 static SOCKET socket_connect(
const char *host,
const char *port)
149 #define __err_connect(func) \
151 fprintf(stderr, "%s: %d\n", func, WSAGetLastError()); \
157 struct linger lng = { 0, 0 };
158 struct sockaddr_in server;
159 struct hostent *hp = 0;
161 if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
__err_connect(
"socket");
162 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (
char*)&on,
sizeof(on)) == -1)
__err_connect(
"setsockopt");
163 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (
char*)&lng,
sizeof(lng)) == -1)
__err_connect(
"setsockopt");
165 if (isalpha(host[0])) hp = gethostbyname(host);
168 addr.s_addr = inet_addr(host);
169 hp = gethostbyaddr((
char*)&addr, 4, AF_INET);
173 server.sin_addr.s_addr = *((
unsigned long*)hp->h_addr);
174 server.sin_family= AF_INET;
175 server.sin_port = htons(atoi(port));
176 if (connect(fd, (
struct sockaddr*)&server,
sizeof(server)) != 0)
__err_connect(
"connect");
182 static off_t my_netread(
int fd,
void *buf, off_t len)
184 off_t rest = len, curr, l = 0;
188 if (socket_wait(fd, 1) <= 0)
break;
189 curr =
netread(fd, (
void*)((
char*)buf + l), rest);
194 if (curr == 0)
break;
195 l += curr; rest -= curr;
204 static int kftp_get_response(
knetFile *ftp)
213 if (socket_wait(ftp->
ctrl_fd, 1) <= 0)
return 0;
228 if (n < 2)
return -1;
230 return strtol(ftp->
response, &p, 0);
233 static int kftp_send_cmd(
knetFile *ftp,
const char *cmd,
int is_get)
235 if (socket_wait(ftp->
ctrl_fd, 0) <= 0)
return -1;
236 int len = strlen(cmd);
238 return is_get? kftp_get_response(ftp) : 0;
241 static int kftp_pasv_prep(
knetFile *ftp)
245 kftp_send_cmd(ftp,
"PASV\r\n", 1);
246 for (p = ftp->
response; *p && *p !=
'('; ++p);
247 if (*p !=
'(')
return -1;
249 sscanf(p,
"%d,%d,%d,%d,%d,%d", &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
250 memcpy(ftp->
pasv_ip, v, 4 *
sizeof(
int));
251 ftp->
pasv_port = (v[4]<<8&0xff00) + v[5];
256 static int kftp_pasv_connect(
knetFile *ftp)
258 char host[80], port[10];
260 fprintf(stderr,
"[kftp_pasv_connect] kftp_pasv_prep() is not called before hand.\n");
265 ftp->
fd = socket_connect(host, port);
266 if (ftp->
fd == -1)
return -1;
273 if (ftp->
ctrl_fd == -1)
return -1;
274 kftp_get_response(ftp);
275 kftp_send_cmd(ftp,
"USER anonymous\r\n", 1);
276 kftp_send_cmd(ftp,
"PASS kftp@\r\n", 1);
277 kftp_send_cmd(ftp,
"TYPE I\r\n", 1);
298 if (strstr(fn,
"ftp://") != fn)
return 0;
299 for (p = (
char*)fn + 6; *p && *p !=
'/'; ++p);
300 if (*p !=
'/')
return 0;
307 fp->
port = strdup(
"21");
308 fp->
host = (
char*)calloc(l + 1, 1);
310 strncpy(fp->
host, fn + 6, l);
311 fp->
retr = (
char*)calloc(strlen(p) + 8, 1);
312 sprintf(fp->
retr,
"RETR %s\r\n", p);
313 fp->
size_cmd = (
char*)calloc(strlen(p) + 8, 1);
314 sprintf(fp->
size_cmd,
"SIZE %s\r\n", p);
330 if ( sscanf(fp->
response,
"%*d %lld", &file_size) != 1 )
332 fprintf(stderr,
"[kftp_connect_file] %s\n", fp->
response);
337 while (*p !=
' ') ++p;
338 while (*p < '0' || *p >
'9') ++p;
339 file_size = strtoint64(p);
345 sprintf(tmp,
"REST %lld\r\n", (
long long)fp->
offset);
347 strcpy(tmp,
"REST ");
348 int64tostr(tmp + 5, fp->
offset);
351 kftp_send_cmd(fp, tmp, 1);
353 kftp_send_cmd(fp, fp->
retr, 0);
354 kftp_pasv_connect(fp);
355 ret = kftp_get_response(fp);
357 fprintf(stderr,
"[kftp_connect_file] %s\n", fp->
response);
376 if (strstr(fn,
"http://") != fn)
return 0;
378 for (p = (
char*)fn + 7; *p && *p !=
'/'; ++p);
384 for (q = fp->
http_host; *q && *q !=
':'; ++q);
385 if (*q ==
':') *q++ = 0;
387 proxy = getenv(
"http_proxy");
391 fp->
port = strdup(*q? q :
"80");
392 fp->
path = strdup(*p? p :
"/");
394 fp->
host = (strstr(proxy,
"http://") == proxy)? strdup(proxy + 7) : strdup(proxy);
395 for (q = fp->
host; *q && *q !=
':'; ++q);
396 if (*q ==
':') *q++ = 0;
397 fp->
port = strdup(*q? q :
"80");
398 fp->
path = strdup(fn);
412 buf = (
char*)calloc(0x10000, 1);
413 l += sprintf(buf + l,
"GET %s HTTP/1.0\r\nHost: %s\r\n", fp->
path, fp->
http_host);
414 l += sprintf(buf + l,
"Range: bytes=%lld-\r\n", (
long long)fp->
offset);
415 l += sprintf(buf + l,
"\r\n");
416 if (
netwrite(fp->
fd, buf, l) != l )
return -1;
419 if (buf[l] ==
'\n' && l >= 3)
420 if (strncmp(buf + l - 3,
"\r\n\r\n", 4) == 0)
break;
429 ret = strtol(buf + 8, &p, 0);
430 if (ret == 200 && fp->
offset>0) {
433 off_t l = rest < 0x10000? rest : 0x10000;
434 rest -= my_netread(fp->
fd, buf, l);
436 }
else if (ret != 206 && ret != 200) {
438 fprintf(stderr,
"[khttp_connect_file] fail to open file (HTTP code: %d).\n", ret);
455 if (mode[0] !=
'r') {
456 fprintf(stderr,
"[kftp_open] only mode \"r\" is supported.\n");
459 if (strstr(fn,
"ftp://") == fn) {
461 if (fp == 0)
return 0;
467 }
else if (strstr(fn,
"http://") == fn) {
469 if (fp == 0)
return 0;
476 int fd = open(fn, O_RDONLY | O_BINARY);
478 int fd = open(fn, O_RDONLY);
489 if (fp && fp->
fd == -1) {
507 if (fp->
fd == -1)
return 0;
522 curr =
read(fp->
fd, (
void*)((
char*)buf + l), rest);
523 }
while (curr < 0 && EINTR == errno);
524 if (curr < 0)
return -1;
525 if (curr == 0)
break;
526 l += curr; rest -= curr;
528 }
else l = my_netread(fp->
fd, buf, len);
538 off_t offset = lseek(fp->
fd, off, whence);
539 if (offset == -1)
return -1;
551 fprintf(stderr,
"[knet_seek] SEEK_END is not supported for HTTP. Offset is unchanged.\n");
562 fprintf(stderr,
"[knet_seek] %s\n", strerror(errno));
568 if (fp == 0)
return 0;
592 buf = calloc(0x100000, 1);
596 }
else if (type == 1) {
597 fp =
knet_open(
"ftp://ftp.ncbi.nih.gov/1000genomes/ftp/data/NA12878/alignment/NA12878.chrom6.SLX.SRP000032.2009_06.bam",
"r");
600 }
else if (type == 2) {
601 fp =
knet_open(
"ftp://ftp.sanger.ac.uk/pub4/treefam/tmp/index.shtml",
"r");
603 }
else if (type == 3) {
604 fp =
knet_open(
"http://www.sanger.ac.uk/Users/lh3/index.shtml",
"r");
606 }
else if (type == 4) {
607 fp =
knet_open(
"http://www.sanger.ac.uk/Users/lh3/ex1.bam",
"r");
611 l =
knet_read(fp, buf+10000, 10000000) + 10000;
613 if (type != 4 && type != 1) {
617 }
else write(fileno(stdout), buf, l);