/*--成功返回连接句柄 Handle,失败返回-1---*/ int network_tcp_connection_open(uint8 *hostname, uint16 port) { int handle=-1; handle = util_tcp_connect(hostname, port); return handle; }
int ftp_transfer(UrlResource *rsrc, libnet_callback notify) { Url *u = NULL; FILE *out = NULL; char *line = NULL; int sock = -1; int data_sock = -1; int passive = 1; int retval = 0; int msg_code = 0; u = rsrc->url; /* first of all, if this is proxied, just pass it off to the http module, since that's how we support proxying. */ rsrc->proxy = get_proxy("FTP_PROXY"); if ( rsrc->proxy ) { return http_transfer(rsrc, notify); } ftp_set_defaults(rsrc, u); sock = util_tcp_connect(u->host, u->port); if (sock < 0) { if (rsrc->running) { notify(NET_MSG_DOWNLOAD_FINISH, (UINT32)-NET_ERR_CONNECT_FAILED); } //S_CLOSE(sock); return 0; } if ( !(line = get_line(rsrc, sock)) ) { if (rsrc->running) { notify(NET_MSG_DOWNLOAD_FINISH, (UINT32)-NET_ERR_FTP_SERVER_ERROR); } S_CLOSE(sock); return 0; } if ( !check_numeric("220", line) ) { safe_free(line); S_CLOSE(sock); LIBNET_DEBUG("bad server greeting"); if (rsrc->running) { notify(NET_MSG_DOWNLOAD_FINISH, (UINT32)-NET_ERR_FTP_SERVER_ERROR); } return 0; } safe_free(line); send_control(sock, "USER ", u->username, "\r\n", NULL); if ( !(line = get_line(rsrc, sock)) ) { msg_code = -NET_ERR_LOGIN_FAILED; goto cleanup; } /* do the password dance */ if ( !check_numeric("230", line) ) { if ( !check_numeric("331", line)) { safe_free(line); LIBNET_DEBUG("bad/unexpected response: %s", line); msg_code = -NET_ERR_LOGIN_FAILED; goto cleanup; } else { safe_free(line); send_control(sock, "PASS ", u->password, "\r\n", NULL); if ( !((line = get_line(rsrc, sock)) && check_numeric("230", line)) ) { safe_free(line); LIBNET_DEBUG("login failed"); msg_code = -NET_ERR_LOGIN_FAILED; goto cleanup; } //safe_free(line); } } safe_free(line); /* set binmode */ send_control(sock, "TYPE I\r\n", NULL); if ( !(line = get_line(rsrc, sock)) ) { msg_code = -NET_ERR_FTP_SERVER_ERROR; goto cleanup; } safe_free(line); #if 1 // user can't change ftp path to "/" if server don't support it if ( u->path && (STRCMP(u->path, "/") != 0)) { /* CWD using relative path */ char *relative_path = u->path[0] == '/' ? &u->path[1] : &u->path[0]; send_control(sock, "CWD ", relative_path, "\r\n", NULL); if ( !((line = get_line(rsrc, sock)) && check_numeric("250", line)) ) { safe_free(line); msg_code = -NET_ERR_OPERATION_NOT_PERMIT; goto cleanup; } safe_free(line); } #endif /* finally, the good stuff */ /* get a socket for reading. try passive first. */ if ( ! (rsrc->options & OPT_ACTIVE) ) { if ( (data_sock = get_passive_sock(rsrc, sock)) < 0 ) { msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } } if ( data_sock < 0 ) { if ( (data_sock = get_sock(rsrc, sock)) < 1 ) { msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } else passive = 0; } if (u->file) { send_control(sock, "SIZE ", u->file, "\r\n", NULL); line = get_line(rsrc, sock); if (line && check_numeric("213", line)) { rsrc->outfile_size = ATOI(line + 4); } else if (line && check_numeric("550", line)) { safe_free(line); msg_code = -NET_ERR_FILE_NOT_FOUND; goto cleanup; } else { rsrc->outfile_size = 0; } if (line) FREE(line); } /* handle resume */ if ( rsrc->outfile_offset && (rsrc->options & OPT_RESUME) ) { char numstring[32]; /* ugly hack */ sprintf(numstring, "%ld", (long int )rsrc->outfile_offset); send_control(sock, "REST ", numstring, "\r\n", NULL); if ( !((line = get_line(rsrc, sock)) && check_numeric("350", line)) ) { safe_free(line); LIBNET_DEBUG("server does not support FTP resume, try again without -r"); msg_code = -NET_ERR_OPERATION_NOT_PERMIT; goto cleanup; } safe_free(line); } if (u->file) send_control(sock, "RETR ", u->file, "\r\n", NULL); else send_control(sock, "NLST\r\n", NULL); if ( !((line = get_line(rsrc, sock)) && (check_numeric("150", line) || check_numeric("125", line))) ) { safe_free(line); msg_code = -NET_ERR_OPERATION_NOT_PERMIT; goto cleanup; } LIBNET_DEBUG("ftp reply(RETR): %s\n", line); if ( !passive ) data_sock = S_ACCEPT(data_sock, NULL, NULL); /* rsrc->outfile_size = guess_file_size(line); */ safe_free(line); if (rsrc->outfile) { if (get_file_size(rsrc->outfile) > 0) out = fopen(rsrc->outfile, "rb+"); else out = fopen(rsrc->outfile, "wb"); if ( !out ) { //report(ERR, "opening %s: %s", rsrc->outfile, // strerror(errno)); msg_code = -NET_ERR_FILE_SAVE_ERROR; goto cleanup; } } retval = dump_data(rsrc, data_sock, out, notify); if (rsrc->running) { line = get_line(rsrc, sock); /* 226 Transfer complete */ LIBNET_DEBUG("ftp(done): %s\n", line); safe_free(line); } cleanup: send_control(sock, "QUIT\r\n", NULL); line = get_line(rsrc, sock); /* 221 Goodbye */ LIBNET_DEBUG("ftp(QUIT): %s\n", line); safe_free(line); if (out) fclose(out); if (data_sock >= 0) { S_CLOSE(data_sock); } if (sock >= 0) { S_CLOSE(sock); } #ifndef WIN32 if (rsrc->outfile) fs_sync(rsrc->outfile); #endif if (msg_code < 0 && rsrc->running) { notify(NET_MSG_DOWNLOAD_FINISH, (UINT32)msg_code); } return retval; }
int http_transfer(UrlResource *rsrc, libnet_callback notify) { FILE *out = NULL; Url *u = NULL; Url *proxy_url = NULL; Url *redir_u = NULL; char *request = NULL; //char *raw_header = NULL; HttpHeader *header = NULL; //char *len_string = NULL; //char *new_location = NULL; char *tmp_string = NULL; //char buf[BUFSIZE]; int sock = -1; ssize_t bytes_read = 0; int msg_code = 0; int retval = 0; int i; char *buf = MALLOC(BUFSIZE); if (!buf) { LIBNET_DEBUG("No enough memory!\n"); return 0; } /* make sure we haven't recursed too much */ if ( redirect_count > REDIRECT_MAX ) { LIBNET_DEBUG("redirection max count exceeded (looping redirect?)"); redirect_count = 0; msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } /* make sure everything's initialized to something useful */ u = rsrc->url; if ( !u->host ) { LIBNET_DEBUG("no host specified"); msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } /* fill in proxyness */ if ( !rsrc->proxy ) { rsrc->proxy = get_proxy("HTTP_PROXY"); } if (( NULL == rsrc->outfile ) && (NULL == rsrc->buffer)) { if ( u->file ) rsrc->outfile = strdup(u->file); else rsrc->outfile = strdup("index.html"); } if ( !u->path ) u->path = strdup("/"); if ( !u->file ) u->file = strdup(""); /* funny looking */ if ( !u->port ) u->port = 80; rsrc->options |= default_opts; /* send the request to either the proxy or the remote host */ if ( rsrc->proxy ) { proxy_url = url_new(); url_init(proxy_url, rsrc->proxy); if ( !proxy_url->port ) proxy_url->port = 80; if ( !proxy_url->host ) { LIBNET_DEBUG( "bad proxy `%s'", rsrc->proxy); msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } if ( proxy_url->username ) rsrc->proxy_username = strdup(proxy_url->username); if ( proxy_url->password ) rsrc->proxy_password = strdup(proxy_url->password); #ifdef LIB_W5300 sock = w5300_tcp_connect(proxy_url->host, proxy_url->port, rsrc->srcip, rsrc->srcport); #else sock = util_tcp_connect(proxy_url->host, proxy_url->port); #endif if (sock < 0) { msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } safe_free(u->path); safe_free(u->file); u->path = strdup(""); u->file = strdup(u->full_url); request = get_request(rsrc); LIBNET_DEBUG("sending request:\n%s", request); S_WRITE(sock, request, STRLEN(request)); FREE(request); } else /* no proxy */ { #ifdef LIB_W5300 sock = w5300_tcp_connect(u->host, u->port, rsrc->srcip, rsrc->srcport); #else sock = util_tcp_connect(u->host, u->port); #endif if (sock < 0) { msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } request = get_request(rsrc); LIBNET_DEBUG("sending request:\n%s", request); S_WRITE(sock, request, STRLEN(request)); FREE(request); } if (rsrc->outfile) { if ((get_file_size(rsrc->outfile) > 0) && (rsrc->options & OPT_RESUME)) out = fopen(rsrc->outfile, "rb+"); else out = fopen(rsrc->outfile, "wb"); if ( !out ) { LIBNET_DEBUG( "opening %s: %s", rsrc->outfile, ""); msg_code = -NET_ERR_FILE_SAVE_ERROR; goto cleanup; } } /* check to see if it returned a HTTP 1.x response */ MEMSET(buf, '\0', 5); #ifdef LIB_W5300 bytes_read = S_READ(sock, buf, BUFSIZE); buf[bytes_read] = '\0'; LIBNET_DEBUG("receive respond:(%d)\n%s", bytes_read, buf); #else bytes_read = S_READ(sock, buf, 8); #endif if ( bytes_read <= 0 ) { msg_code = -NET_ERR_HTTP_SERVER_ERROR; goto cleanup; } if ( ! (buf[0] == 'H' && buf[1] == 'T' && buf[2] == 'T' && buf[3] == 'P') ) { if((rsrc->options & OPT_RESUME) && rsrc->outfile_offset) { LIBNET_DEBUG("server does not support resume!"); msg_code = -NET_ERR_OPERATION_NOT_PERMIT; goto cleanup; } //fwrite(buf, bytes_read, 1,out); } else { /* skip the header */ #ifdef LIB_W5300 buf[bytes_read] = '\0'; #else char *raw_header1 = NULL; buf[bytes_read] = '\0'; raw_header1 = get_raw_header(sock); strconcat2(buf, raw_header1, NULL); FREE(raw_header1); LIBNET_DEBUG("receive respond:(%d)\n%s", bytes_read, buf); #endif header = make_http_header(buf); /* check for redirects */ tmp_string = get_header_value("location", header); if (buf[9] == '3' && tmp_string ) { #if 1 //diable redirec function redir_u = url_new(); /* make sure we still send user/password along */ redir_u->username = safe_strdup(u->username); redir_u->password = safe_strdup(u->password); url_init(redir_u, tmp_string); rsrc->url = redir_u; redirect_count++; //retval = transfer(rsrc, notify); transfer((UINT32)rsrc, (UINT32)notify); rsrc->url =u; redirect_count--; if(redirect_count<0) redirect_count=0; if (redir_u) { url_destroy(redir_u); FREE(redir_u); } #endif FREE(tmp_string); tmp_string = NULL; //msg_code = -NET_ERR_OPERATION_NOT_PERMIT;//we can support redirect now, remove this line. goto cleanup; } if (tmp_string) { FREE(tmp_string); tmp_string = NULL; } if (buf[9] == '4' || buf[9] == '5') { for (i = 0; buf[i] && buf[i] != '\n'; i++); buf[i] = '\0'; LIBNET_DEBUG("HTTP error from server: %s\n", buf); if( buf[9] == '4' && buf[10] == '0' && buf[11] == '4') msg_code = -NET_ERR_FILE_NOT_FOUND; else msg_code = -NET_ERR_HTTP_SERVER_ERROR; goto cleanup; } tmp_string = get_header_value("content-length", header); if (tmp_string) { rsrc->outfile_size = (off_t )ATOI(tmp_string); FREE(tmp_string); tmp_string = NULL; if(rsrc->use_pecache ==0) { if ((rsrc->buffer) && (rsrc->buffer_len < rsrc->outfile_size)) { LIBNET_DEBUG("the buffer length less than the file fize (%d < %d)\n", rsrc->buffer, (int)rsrc->outfile_size); msg_code = -NET_ERR_FILE_SAVE_ERROR; goto cleanup; } } } tmp_string = get_header_value("content-range", header); if (tmp_string) { FREE(tmp_string); tmp_string = NULL; rsrc->outfile_size += rsrc->outfile_offset; } if ((!rsrc->outfile_size) && (rsrc->options & OPT_RESUME) && !(rsrc->options & OPT_NORESUME) && rsrc->outfile_offset ) { LIBNET_DEBUG("unable to determine remote file size"); msg_code = -NET_ERR_FILE_SAVE_ERROR; goto cleanup; } } if(rsrc->use_pecache ==0) retval = dump_data(rsrc, sock, out, notify); else retval = dump_data_to_pecache(rsrc, sock, out, notify); cleanup: free_http_header(header); //if (raw_header) // FREE(raw_header); if (proxy_url) { url_destroy(proxy_url); FREE(proxy_url); } if (sock >= 0) { S_CLOSE(sock); } if (out) fclose(out); if (buf) { FREE(buf); } #ifndef WIN32 if (rsrc->outfile) fs_sync(rsrc->outfile); #endif if (msg_code < 0 && rsrc->running) { notify(NET_MSG_DOWNLOAD_FINISH, (UINT32)msg_code); libnet_abort_url_read(TRUE);//to break url_open while loop //retval!=1 means transfer fail } return retval; }