static void* masterproxy_acceptor(void *args) { pthread_t clientthread; pthread_attr_t thattr; int sock; (void)args; pthread_attr_init(&thattr); pthread_attr_setstacksize(&thattr,0x100000); pthread_attr_setdetachstate(&thattr,PTHREAD_CREATE_DETACHED); while (terminate==0) { sock = tcptoaccept(lsock,1000); if (sock>=0) { int *s = malloc(sizeof(int)); // memory is freed inside pthread routine !!! *s = sock; tcpnodelay(sock); if (pthread_create(&clientthread,&thattr,masterproxy_server,s)<0) { free(s); tcpclose(sock); } } } pthread_attr_destroy(&thattr); return NULL; }
void* ppfs_fsinit( struct fuse_conn_info* conn ) { //connect to MDS fprintf(stderr, "ppfs_fsinit\n"); if((fd = tcpsocket())<0) { fprintf(stderr, "can't create socket\n"); exit(1); } else { fprintf(stderr, "fd:%d\n", fd); } tcpnodelay(fd); if(tcpstrconnect(fd, ip, MDS_PORT_STR)<0) { fprintf(stderr, "can't connect to MDS (%s:%s)\n", ip, port); fd = -1; exit(1); } fprintf(stderr, "ppfs_init create socket: %u\n", fd); local_mds.sockfd = fd; tcpgetpeer(fd,&(local_mds.peerip),NULL); remote_mds.sockfd = -1; remote_mds.peerip = -1; }
int masterproxy_init(void) { pthread_attr_t thattr; lsock = tcpsocket(); if (lsock<0) { //mfs_errlog(LOG_ERR,"main master server module: can't create socket"); return -1; } tcpnonblock(lsock); tcpnodelay(lsock); // tcpreuseaddr(lsock); if (tcpsetacceptfilter(lsock)<0 && errno!=ENOTSUP) { // mfs_errlog_silent(LOG_NOTICE,"master proxy: can't set accept filter"); } if (tcpstrlisten(lsock,"127.0.0.1",0,100)<0) { // mfs_errlog(LOG_ERR,"main master server module: can't listen on socket"); tcpclose(lsock); lsock = -1; return -1; } if (tcpgetmyaddr(lsock,&proxyhost,&proxyport)<0) { tcpclose(lsock); lsock = -1; return -1; } terminate = 0; pthread_attr_init(&thattr); pthread_attr_setstacksize(&thattr,0x100000); //pthread_create(&proxythread,&thattr,masterproxy_loop,NULL); pthread_create(&proxythread,&thattr,masterproxy_acceptor,NULL); pthread_attr_destroy(&thattr); return 1; }
int matomlserv_init(void) { ListenHost = cfg_getstr("MATOML_LISTEN_HOST","*"); ListenPort = cfg_getstr("MATOML_LISTEN_PORT","9419"); lsock = tcpsocket(); if (lsock<0) { mfs_errlog(LOG_ERR,"master <-> metaloggers module: can't create socket"); return -1; } tcpnonblock(lsock); tcpnodelay(lsock); tcpreuseaddr(lsock); if (tcpsetacceptfilter(lsock)<0 && errno!=ENOTSUP) { mfs_errlog_silent(LOG_NOTICE,"master <-> metaloggers module: can't set accept filter"); } if (tcpstrlisten(lsock,ListenHost,ListenPort,100)<0) { mfs_arg_errlog(LOG_ERR,"master <-> metaloggers module: can't listen on %s:%s",ListenHost,ListenPort); return -1; } mfs_arg_syslog(LOG_NOTICE,"master <-> metaloggers module: listen on %s:%s",ListenHost,ListenPort); matomlservhead = NULL; ChangelogSecondsToRemember = cfg_getuint16("MATOML_LOG_PRESERVE_SECONDS",600); if (ChangelogSecondsToRemember>3600) { syslog(LOG_WARNING,"Number of seconds of change logs to be preserved in master is too big (%"PRIu16") - decreasing to 3600 seconds",ChangelogSecondsToRemember); ChangelogSecondsToRemember=3600; } main_reloadregister(matomlserv_reload); main_destructregister(matomlserv_term); main_canexitregister(matomlserv_canexit); main_pollregister(matomlserv_desc,matomlserv_serve); main_timeregister(TIMEMODE_SKIP_LATE,3600,0,matomlserv_status); return 0; }
int matomlserv_init(void) { ListenHost = cfg_getstr("MATOML_LISTEN_HOST","*"); ListenPort = cfg_getstr("MATOML_LISTEN_PORT","9419"); lsock = tcpsocket(); if (lsock<0) { mfs_errlog(LOG_ERR,"master <-> metaloggers module: can't create socket"); return -1; } tcpnonblock(lsock); tcpnodelay(lsock); tcpreuseaddr(lsock); if (tcpsetacceptfilter(lsock)<0 && errno!=ENOTSUP) { mfs_errlog_silent(LOG_NOTICE,"master <-> metaloggers module: can't set accept filter"); } if (tcpstrlisten(lsock,ListenHost,ListenPort,100)<0) { mfs_errlog(LOG_ERR,"master <-> metaloggers module: can't listen on socket"); return -1; } mfs_arg_syslog(LOG_NOTICE,"master <-> metaloggers module: listen on %s:%s",ListenHost,ListenPort); matomlservhead = NULL; main_reloadregister(matomlserv_reload); main_destructregister(matomlserv_term); main_pollregister(matomlserv_desc,matomlserv_serve); main_timeregister(TIMEMODE_SKIP_LATE,3600,0,matomlserv_status); return 0; }
void masterconn_connected(masterconn *eptr) { double now; now = monotonic_seconds(); tcpnodelay(eptr->sock); eptr->mode = DATA; eptr->lastread = now; eptr->lastwrite = now; eptr->input_bytesleft = 8; eptr->input_startptr = eptr->input_hdr; eptr->input_end = 0; eptr->input_packet = NULL; eptr->inputhead = NULL; eptr->inputtail = &(eptr->inputhead); eptr->outputhead = NULL; eptr->outputtail = &(eptr->outputhead); eptr->conncnt++; eptr->masterversion = 0; eptr->hlstatus = 0; eptr->gotrndblob = 0; memset(eptr->rndblob,0,32); eptr->registerstate = UNREGISTERED; masterconn_sendregister(eptr); }
int csserv_init(void) { ListenHost = cfg_getstr("CSSERV_LISTEN_HOST","*"); ListenPort = cfg_getstr("CSSERV_LISTEN_PORT",DEFAULT_CS_DATA_PORT); lsock = tcpsocket(); if (lsock<0) { mfs_errlog(LOG_ERR,"main server module: can't create socket"); return -1; } tcpnonblock(lsock); tcpnodelay(lsock); tcpreuseaddr(lsock); tcpresolve(ListenHost,ListenPort,&mylistenip,&mylistenport,1); if (tcpnumlisten(lsock,mylistenip,mylistenport,100)<0) { mfs_errlog(LOG_ERR,"main server module: can't listen on socket"); return -1; } if (tcpsetacceptfilter(lsock)<0 && errno!=ENOTSUP) { mfs_errlog_silent(LOG_NOTICE,"main server module: can't set accept filter"); } mfs_arg_syslog(LOG_NOTICE,"main server module: listen on %s:%s",ListenHost,ListenPort); csservhead = NULL; main_reload_register(csserv_reload); main_destruct_register(csserv_term); main_poll_register(csserv_desc,csserv_serve); return 0; }
int client_socket (char * host, char * port) { int status; int lsock = tcpsocket(); if (lsock<0) { logging(LOG_ERROR, "can't create socket !!!"); return -1; } if (tcpnonblock(lsock)<0) { logging(LOG_ERROR, "set nonblock, error: %m"); tcpclose(lsock); return -1; } status = tcpstrconnect(lsock, host, port); if (status<0) { logging(LOG_WARN, "connect failed, error: %m"); tcpclose(lsock); return -1; } if (status==0) { // connected immediately logging(LOG_INFO,"connected immediately"); tcpnodelay(lsock); } else { logging(LOG_INFO,"connecting to %s:%s...", host, port); } return lsock; }
static int write_data_refresh_connection(uint32_t inode, uint32_t indx, uint64_t *chunkid) { uint32_t ip; uint16_t port; uint8_t status; if (rw_sock >= 0) { tcpclose(rw_sock); rw_sock = -1; } status = fs_writechunk(&ip,&port, chunkid, inode, indx); if (status != 0) { fprintf(stderr, "status error\n"); return -2; } rw_sock = tcpsocket(); if (rw_sock < 0) { fprintf(stderr,"can't create tcp socket\n"); return -1; } if (tcpnodelay(rw_sock)<0) { fprintf(stderr,"can't set TCP_NODELAY\n"); } if (tcpnumconnect(rw_sock, ip, port)<0) { fprintf(stderr,"can't connect to (%d.%d.%d.%d:%u)\n", ip/(256*256*256)%256, ip/(256*256)%256, ip/256%256, ip%256, port); tcpclose(rw_sock); rw_sock = -1; return -1; } return 0; }
void matoslaserv_serve(int epoll_fd,int count,struct epoll_event *pdesc) { //uint32_t now=main_time(); serventry *eptr,*weptr; int ns; weptr = (serventry *)pdesc[count].data.ptr; if ((weptr->listen_sock == 1) && (pdesc[count].events & EPOLLIN)) { ns=tcpaccept(lsock); if (ns<0) { MFSLOG(LOG_INFO,"Master<->sla socket: accept error: %m"); } else { struct epoll_event ev; tcpnonblock(ns); tcpnodelay(ns); eptr = (serventry *)malloc(sizeof(serventry)); eptr->next = matoslaservhead; matoslaservhead = eptr; eptr->sock = ns; eptr->mode = HEADER; eptr->lastread = eptr->lastwrite = get_current_time(); eptr->inputpacket.next = NULL; eptr->inputpacket.bytesleft = 8; eptr->inputpacket.startptr = eptr->hdrbuff; eptr->inputpacket.packet = NULL; eptr->outputhead = NULL; eptr->outputtail = &(eptr->outputhead); eptr->timeout = 120; tcpgetpeer(eptr->sock,&(eptr->servip),NULL); eptr->servstrip = matoslaserv_makestrip(eptr->servip); eptr->version=0; eptr->metafd=-1; eptr->listen_sock = 0; eptr->connection = 4; ev.data.ptr = eptr; ev.events = EPOLLIN | EPOLLOUT; epoll_ctl(epoll_fd,EPOLL_CTL_ADD,ns,&ev); } } if(weptr->listen_sock == 0) { if (pdesc[count].events & (EPOLLERR|EPOLLHUP)) { weptr->mode = KILL; } if ((pdesc[count].events & EPOLLIN) && weptr->mode!=KILL) { matoslaserv_read(weptr); weptr->lastread = get_current_time(); } if ((pdesc[count].events & EPOLLOUT) && weptr->mode!=KILL && weptr->outputhead!=NULL) { matoslaserv_write(weptr); weptr->lastwrite = get_current_time(); } } }
void masterconn_connected(serventry *eptr) { tcpnodelay(eptr->sock); eptr->mode=HEADER; eptr->inputpacket.next = NULL; eptr->inputpacket.bytesleft = 8; eptr->inputpacket.startptr = eptr->hdrbuff; eptr->inputpacket.packet = NULL; eptr->outputtail = &(eptr->outputhead); masterconn_sendregister(eptr); eptr->lastread = eptr->lastwrite = get_current_time(); }
void matomlserv_reload(void) { char *oldListenHost,*oldListenPort; int newlsock; oldListenHost = ListenHost; oldListenPort = ListenPort; ListenHost = cfg_getstr("MATOML_LISTEN_HOST","*"); ListenPort = cfg_getstr("MATOML_LISTEN_PORT","9419"); if (strcmp(oldListenHost,ListenHost)==0 && strcmp(oldListenPort,ListenPort)==0) { free(oldListenHost); free(oldListenPort); mfs_arg_syslog(LOG_NOTICE,"master <-> metaloggers module: socket address hasn't changed (%s:%s)",ListenHost,ListenPort); return; } newlsock = tcpsocket(); if (newlsock<0) { mfs_errlog(LOG_WARNING,"master <-> metaloggers module: socket address has changed, but can't create new socket"); free(ListenHost); free(ListenPort); ListenHost = oldListenHost; ListenPort = oldListenPort; return; } tcpnonblock(newlsock); tcpnodelay(newlsock); tcpreuseaddr(newlsock); if (tcpsetacceptfilter(newlsock)<0 && errno!=ENOTSUP) { mfs_errlog_silent(LOG_NOTICE,"master <-> metaloggers module: can't set accept filter"); } if (tcpstrlisten(newlsock,ListenHost,ListenPort,100)<0) { mfs_arg_errlog(LOG_ERR,"master <-> metaloggers module: socket address has changed, but can't listen on socket (%s:%s)",ListenHost,ListenPort); free(ListenHost); free(ListenPort); ListenHost = oldListenHost; ListenPort = oldListenPort; tcpclose(newlsock); return; } mfs_arg_syslog(LOG_NOTICE,"master <-> metaloggers module: socket address has changed, now listen on %s:%s",ListenHost,ListenPort); free(oldListenHost); free(oldListenPort); tcpclose(lsock); lsock = newlsock; ChangelogSecondsToRemember = cfg_getuint16("MATOML_LOG_PRESERVE_SECONDS",600); if (ChangelogSecondsToRemember>3600) { syslog(LOG_WARNING,"Number of seconds of change logs to be preserved in master is too big (%"PRIu16") - decreasing to 3600 seconds",ChangelogSecondsToRemember); ChangelogSecondsToRemember=3600; } }
void masterconn_connected(masterconn *eptr) { tcpnodelay(eptr->sock); eptr->mode=HEADER; eptr->inputpacket.next = NULL; eptr->inputpacket.bytesleft = 8; eptr->inputpacket.startptr = eptr->hdrbuff; eptr->inputpacket.packet = NULL; eptr->outputhead = NULL; eptr->outputtail = &(eptr->outputhead); masterconn_sendregister(eptr); masterconn_metadownloadinit(); eptr->lastread = eptr->lastwrite = main_time(); }
//向Master注册,调用masterconn_sendregister()封装注册packet //调用:masterconn_initconnect() void masterconn_connected(masterconn *eptr) { #ifdef BGJOBS eptr->jpool = job_pool_new(10,BGJOBSCNT,&(eptr->jobfd)); #endif tcpnodelay(eptr->sock); eptr->mode=HEADER; eptr->inputpacket.next = NULL; eptr->inputpacket.bytesleft = 8; eptr->inputpacket.startptr = eptr->hdrbuff; eptr->inputpacket.packet = NULL; eptr->outputhead = NULL; eptr->outputtail = &(eptr->outputhead); masterconn_sendregister(eptr); eptr->lastread = eptr->lastwrite = main_time(); }
void csserv_reload(void) { char *oldListenHost,*oldListenPort; int newlsock; // ThreadedServer = 1-ThreadedServer; oldListenHost = ListenHost; oldListenPort = ListenPort; ListenHost = cfg_getstr("CSSERV_LISTEN_HOST","*"); ListenPort = cfg_getstr("CSSERV_LISTEN_PORT",DEFAULT_CS_DATA_PORT); if (strcmp(oldListenHost,ListenHost)==0 && strcmp(oldListenPort,ListenPort)==0) { free(oldListenHost); free(oldListenPort); mfs_arg_syslog(LOG_NOTICE,"main server module: socket address hasn't changed (%s:%s)",ListenHost,ListenPort); return; } newlsock = tcpsocket(); if (newlsock<0) { mfs_errlog(LOG_WARNING,"main server module: socket address has changed, but can't create new socket"); free(ListenHost); free(ListenPort); ListenHost = oldListenHost; ListenPort = oldListenPort; return; } tcpnonblock(newlsock); tcpnodelay(newlsock); tcpreuseaddr(newlsock); if (tcpstrlisten(newlsock,ListenHost,ListenPort,100)<0) { mfs_arg_errlog(LOG_ERR,"main server module: socket address has changed, but can't listen on socket (%s:%s)",ListenHost,ListenPort); free(ListenHost); free(ListenPort); ListenHost = oldListenHost; ListenPort = oldListenPort; tcpclose(newlsock); return; } if (tcpsetacceptfilter(newlsock)<0 && errno!=ENOTSUP) { mfs_errlog_silent(LOG_NOTICE,"main server module: can't set accept filter"); } mfs_arg_syslog(LOG_NOTICE,"main server module: socket address has changed, now listen on %s:%s",ListenHost,ListenPort); free(oldListenHost); free(oldListenPort); tcpclose(lsock); lsock = newlsock; }
int matoslaserv_init() { ListenHost = cfg_getstr("MATOSLA_LISTEN_HOST","*"); ListenPort = cfg_getstr("MATOSLA_LISTEN_PORT","9423"); BindHost = cfg_getstr("BIND_HOST","*"); MaxReconnect = cfg_getuint32("MAX_RECONNECT",10); sla_worker_addr[0].host = cfg_getstr("SLA_SYNC_WORKER_HOST_1","*"); sla_worker_addr[0].port = cfg_getstr("SLA_SYNC_WORKER_PORT_1","9422"); sla_worker_addr[1].host = cfg_getstr("SLA_SYNC_WORKER_HOST_2","*"); sla_worker_addr[1].port = cfg_getstr("SLA_SSYNC_WORKER_PORT_2","9422"); sla_worker_addr[2].host = cfg_getstr("SLA_SSYNC_WORKER_HOST_3","*"); sla_worker_addr[2].port = cfg_getstr("SLA_SSYNC_WORKER_PORT_3","9422"); sla_worker_addr[3].host = cfg_getstr("SLA_SSYNC_WORKER_HOST_4","*"); sla_worker_addr[3].port = cfg_getstr("SLA_SSYNC_WORKER_PORT_4","9422"); first_add_listen_sock = 0; lsock = tcpsocket(); if (lsock<0) { MFSLOG(LOG_ERR,"matosla: socket error: %m"); fprintf(msgfd,"master <-> metaloggers module: can't create socket\n"); return -1; } tcpnonblock(lsock); tcpnodelay(lsock); tcpreuseaddr(lsock); if (sla_worker_addr_resolve()<0) { MFSLOG(LOG_NOTICE,"sla_worker_addr_resolve failed"); } if (tcpsetacceptfilter(lsock)<0) { MFSLOG(LOG_NOTICE,"matosla: can't set accept filter: %m"); } if (tcpstrlisten(lsock,ListenHost,ListenPort,1024)<0) { MFSLOG(LOG_ERR,"matosla: listen error: %m"); fprintf(msgfd,"master <-> metaloggers module: can't listen on socket\n"); return -1; } MFSLOG(LOG_NOTICE,"matosla: listen on %s:%s",ListenHost,ListenPort); fprintf(msgfd,"master <-> metaloggers module: listen on %s:%s\n",ListenHost,ListenPort); matoslaservhead = NULL; main_destructregister(matoslaserv_term); main_epollregister(matoslaserv_desc,matoslaserv_serve); return 0; }
/* ning: * 这是从 mfs matomlserv.c, matocsserv.c, matocuserv.c 三个代码里面提出来的公用代码 */ int server_socket(char * host, char * port){ int lsock = tcpsocket(); if (lsock<0) { logging(LOG_ERROR, "can't create socket !!!"); return -1; } tcpnonblock(lsock); tcpnodelay(lsock); tcpreuseaddr(lsock); if (tcpsetacceptfilter(lsock)<0) { logging(LOG_INFO,"can't set accept filter: %m"); //TODO: I do not know what this for } if (tcpstrlisten(lsock, host ,port,100)<0) { logging(LOG_ERROR,"can't Listen on socket : %m"); return -1; } logging(LOG_INFO,"listen on %s:%s", host, port); return lsock; }
int serv_connect(ppfs_conn_entry* e,int ip,int port){ int fd = tcpsocket(); if(fd < 0){ fprintf(stderr,"cannot create socket\n"); return -1; } tcpnodelay(fd); if(tcpnumconnect(fd,ip,port) < 0){ fprintf(stderr,"cannot connect to %X:%d\n",ip,port); return -1; } e->sockfd = fd; tcpgetpeer(fd,&(e->peerip),NULL); //@TODO: add login return fd; }
void masterconn_connected(masterconn *eptr) { double now; now = monotonic_seconds(); tcpnodelay(eptr->sock); eptr->mode = DATA; eptr->lastread = now; eptr->lastwrite = now; eptr->input_bytesleft = 8; eptr->input_startptr = eptr->input_hdr; eptr->input_end = 0; eptr->input_packet = NULL; eptr->inputhead = NULL; eptr->inputtail = &(eptr->inputhead); eptr->outputhead = NULL; eptr->outputtail = &(eptr->outputhead); masterconn_sendregister(eptr); if (lastlogversion==0) { masterconn_metadownloadinit(); } }
//initialize listen port int masterconn_initlisten() { lsock = tcpsocket(); if (lsock<0) { MFSLOG(LOG_ERR,"smtoma: socket error: %m"); fprintf(msgfd,"shadow master <-> master module: can't create socket\n"); return -1; } tcpnonblock(lsock); tcpnodelay(lsock); tcpreuseaddr(lsock); if (tcpsetacceptfilter(lsock)<0) { MFSLOG(LOG_NOTICE,"smtoma: can't set accept filter: %m"); } if (tcpstrlisten(lsock,ListenHost,ListenPort,100)<0) { MFSLOG(LOG_ERR,"smtoma: listen port:%s error: %m\n", ListenPort); fprintf(msgfd,"shadow master to master module: can't listen on socket\n"); return -1; } MFSLOG(LOG_NOTICE,"smtoma: listen on %s:%s",ListenHost,ListenPort); fprintf(msgfd,"slave <-> master module: listen on %s:%s\n",ListenHost,ListenPort); return 0; }
int server() { char buffer[1024]; int ss = server_socket("127.0.0.1", "9991"); if (ss < 0) { logging(LOG_ERROR, "socket error!"); return -1; } int ns = tcptoaccept(ss, 100000); if (ns < 0) { logging(LOG_ERROR, "accept error!"); return -1; } tcpnonblock(ns); tcpnodelay(ns); tcptoread(ns, buffer, 10, 3000); /*printf("read ok %d !!\n", n); */ /*printf("read data: \n%s\n", buffer); */ assert(strcmp("helloworl", buffer) == 0); tcpclose(ns); tcpclose(ss); return 0; }
/* singleipconnect() connects to the given IP only, and it may return without having connected if used from the multi interface. */ static curl_socket_t singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, long timeout_ms, bool *connected) { char addr_buf[128]; int rc; int error; bool isconnected; struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res; sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol); if (sockfd == CURL_SOCKET_BAD) return CURL_SOCKET_BAD; *connected = FALSE; /* default is not connected */ Curl_printable_address(ai, addr_buf, sizeof(addr_buf)); infof(data, " Trying %s... ", addr_buf); if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); nosigpipe(conn, sockfd); if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, sockfd, CURLSOCKTYPE_IPCXN); if (error) { sclose(sockfd); /* close the socket and bail out */ return CURL_SOCKET_BAD; } } /* possibly bind the local end to an IP, interface or port */ res = bindlocal(conn, sockfd); if(res) { sclose(sockfd); /* close socket and bail out */ return CURL_SOCKET_BAD; } /* set socket non-blocking */ Curl_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ if(conn->socktype == SOCK_STREAM) rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); else rc = 0; if(-1 == rc) { error = Curl_sockerrno(); switch (error) { case EINPROGRESS: case EWOULDBLOCK: #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK /* On some platforms EAGAIN and EWOULDBLOCK are the * same value, and on others they are different, hence * the odd #if */ case EAGAIN: #endif rc = waitconnect(sockfd, timeout_ms); break; default: /* unknown error, fallthrough and try another address! */ failf(data, "Failed to connect to %s: %s", addr_buf, Curl_strerror(conn,error)); data->state.os_errno = error; break; } } /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from connect(). We can be sure of this since connect() cannot return 1. */ if((WAITCONN_TIMEOUT == rc) && (data->state.used_interface == Curl_if_multi)) { /* Timeout when running the multi interface */ return sockfd; } isconnected = verifyconnect(sockfd, &error); if(!rc && isconnected) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); return sockfd; } else if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); else { data->state.os_errno = error; infof(data, "%s\n", Curl_strerror(conn, error)); } /* connect failed or timed out */ sclose(sockfd); return CURL_SOCKET_BAD; }
/* singleipconnect() connects to the given IP only, and it may return without having connected if used from the multi interface. */ static curl_socket_t singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, long timeout_ms, bool *connected) { struct Curl_sockaddr_ex addr; char addr_buf[128]; int rc; int error; bool isconnected; struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res; const void *iptoprint; struct sockaddr_in * const sa4 = (void *)&addr.sa_addr; #ifdef ENABLE_IPV6 struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; #endif /* * The Curl_sockaddr_ex structure is basically libcurl's external API * curl_sockaddr structure with enough space available to directly hold * any protocol-specific address structures. The variable declared here * will be used to pass / receive data to/from the fopensocket callback * if this has been set, before that, it is initialized from parameters. */ addr.family = ai->ai_family; addr.socktype = conn->socktype; addr.protocol = ai->ai_protocol; addr.addrlen = ai->ai_addrlen; if(addr.addrlen > sizeof(struct Curl_sockaddr_storage)) addr.addrlen = sizeof(struct Curl_sockaddr_storage); memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen); *connected = FALSE; /* default is not connected */ if(data->set.fopensocket) /* * If the opensocket callback is set, all the destination address * information is passed to the callback. Depending on this information the * callback may opt to abort the connection, this is indicated returning * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When * the callback returns a valid socket the destination address information * might have been changed and this 'new' address will actually be used * here to connect. */ sockfd = data->set.fopensocket(data->set.opensocket_client, CURLSOCKTYPE_IPCXN, (struct curl_sockaddr *)&addr); else /* opensocket callback not set, so simply create the socket now */ sockfd = socket(addr.family, addr.socktype, addr.protocol); if(sockfd == CURL_SOCKET_BAD) /* no socket, no connection */ return CURL_SOCKET_BAD; #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) if (conn->scope && (addr.family == AF_INET6)) sa6->sin6_scope_id = conn->scope; #endif /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as argument? */ #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) if(addr.family == AF_UNIX) { infof(data, " Trying %s... ", ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); snprintf(data->info.ip, MAX_IPADR_LEN, "%s", ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); strcpy(conn->ip_addr_str, data->info.ip); } else #endif { #ifdef ENABLE_IPV6 if(addr.family == AF_INET6) { iptoprint = &sa6->sin6_addr; conn->bits.ipv6 = TRUE; } else #endif { iptoprint = &sa4->sin_addr; } if(Curl_inet_ntop(addr.family, iptoprint, addr_buf, sizeof(addr_buf)) != NULL) { infof(data, " Trying %s... ", addr_buf); snprintf(data->info.ip, MAX_IPADR_LEN, "%s", addr_buf); strcpy(conn->ip_addr_str, data->info.ip); } } if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); nosigpipe(conn, sockfd); Curl_sndbufset(sockfd); if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, sockfd, CURLSOCKTYPE_IPCXN); if(error) { sclose(sockfd); /* close the socket and bail out */ return CURL_SOCKET_BAD; } } /* possibly bind the local end to an IP, interface or port */ res = bindlocal(conn, sockfd, addr.family); if(res) { sclose(sockfd); /* close socket and bail out */ return CURL_SOCKET_BAD; } /* set socket non-blocking */ curlx_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ if(conn->socktype == SOCK_STREAM) rc = connect(sockfd, &addr.sa_addr, addr.addrlen); else rc = 0; if(-1 == rc) { error = SOCKERRNO; switch (error) { case EINPROGRESS: case EWOULDBLOCK: #if defined(EAGAIN) #if (EAGAIN) != (EWOULDBLOCK) /* On some platforms EAGAIN and EWOULDBLOCK are the * same value, and on others they are different, hence * the odd #if */ case EAGAIN: #endif #endif rc = waitconnect(conn, sockfd, timeout_ms); break; default: /* unknown error, fallthrough and try another address! */ failf(data, "Failed to connect to %s: %s", addr_buf, Curl_strerror(conn,error)); data->state.os_errno = error; break; } } /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from connect(). We can be sure of this since connect() cannot return 1. */ if((WAITCONN_TIMEOUT == rc) && (data->state.used_interface == Curl_if_multi)) { /* Timeout when running the multi interface */ return sockfd; } isconnected = verifyconnect(sockfd, &error); if(!rc && isconnected) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); Curl_updateconninfo(conn, sockfd); return sockfd; } else if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); else { data->state.os_errno = error; infof(data, "%s\n", Curl_strerror(conn, error)); } /* connect failed or timed out */ sclose(sockfd); return CURL_SOCKET_BAD; }
/* * singleipconnect() * * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to * CURL_SOCKET_BAD. Other errors will however return proper errors. * * singleipconnect() connects to the given IP only, and it may return without * having connected. */ static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, curl_socket_t *sockp) { struct Curl_sockaddr_ex addr; int rc; int error = 0; bool isconnected = FALSE; struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode result; char ipaddress[MAX_IPADR_LEN]; long port; bool is_tcp; *sockp = CURL_SOCKET_BAD; result = Curl_socket(conn, ai, &addr, &sockfd); if(result) /* Failed to create the socket, but still return OK since we signal the lack of socket as well. This allows the parent function to keep looping over alternative addresses/socket families etc. */ return CURLE_OK; /* store remote address and port used in this connection attempt */ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, ipaddress, &port)) { /* malformed address or bug in inet_ntop, try next address */ error = ERRNO; failf(data, "sa_addr inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); Curl_closesocket(conn, sockfd); return CURLE_OK; } infof(data, " Trying %s...\n", ipaddress); is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) && addr.socktype == SOCK_STREAM; if(is_tcp && data->set.tcp_nodelay) tcpnodelay(conn, sockfd); nosigpipe(conn, sockfd); Curl_sndbufset(sockfd); if(is_tcp && data->set.tcp_keepalive) tcpkeepalive(data, sockfd); if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, sockfd, CURLSOCKTYPE_IPCXN); if(error == CURL_SOCKOPT_ALREADY_CONNECTED) isconnected = TRUE; else if(error) { Curl_closesocket(conn, sockfd); /* close the socket and bail out */ return CURLE_ABORTED_BY_CALLBACK; } } /* possibly bind the local end to an IP, interface or port */ if(addr.family == AF_INET || addr.family == AF_INET6) { result = bindlocal(conn, sockfd, addr.family, Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr)); if(result) { Curl_closesocket(conn, sockfd); /* close socket and bail out */ if(result == CURLE_UNSUPPORTED_PROTOCOL) { /* The address family is not supported on this interface. We can continue trying addresses */ return CURLE_COULDNT_CONNECT; } return result; } } /* set socket non-blocking */ (void)curlx_nonblock(sockfd, TRUE); conn->connecttime = Curl_tvnow(); if(conn->num_addr > 1) Curl_expire_latest(data, conn->timeoutms_per_addr); /* Connect TCP sockets, bind UDP */ if(!isconnected && (conn->socktype == SOCK_STREAM)) { rc = connect(sockfd, &addr.sa_addr, addr.addrlen); if(-1 == rc) error = SOCKERRNO; } else { *sockp = sockfd; return CURLE_OK; } #ifdef ENABLE_IPV6 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE; #endif if(-1 == rc) { switch(error) { case EINPROGRESS: case EWOULDBLOCK: #if defined(EAGAIN) #if (EAGAIN) != (EWOULDBLOCK) /* On some platforms EAGAIN and EWOULDBLOCK are the * same value, and on others they are different, hence * the odd #if */ case EAGAIN: #endif #endif result = CURLE_OK; break; default: /* unknown error, fallthrough and try another address! */ infof(data, "Immediate connect fail for %s: %s\n", ipaddress, Curl_strerror(conn,error)); data->state.os_errno = error; /* connect failed */ Curl_closesocket(conn, sockfd); result = CURLE_COULDNT_CONNECT; } } if(!result) *sockp = sockfd; return result; }
/* * singleipconnect() * * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to * CURL_SOCKET_BAD. Other errors will however return proper errors. * * singleipconnect() connects to the given IP only, and it may return without * having connected if used from the multi interface. */ static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, long timeout_ms, curl_socket_t *sockp, bool *connected) { struct Curl_sockaddr_ex addr; int rc; int error = 0; bool isconnected = FALSE; struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res = CURLE_OK; *sockp = CURL_SOCKET_BAD; *connected = FALSE; /* default is not connected */ res = Curl_socket(conn, ai, &addr, &sockfd); if(res) /* Failed to create the socket, but still return OK since we signal the lack of socket as well. This allows the parent function to keep looping over alternative addresses/socket families etc. */ return CURLE_OK; /* store remote address and port used in this connection attempt */ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, conn->primary_ip, &conn->primary_port)) { /* malformed address or bug in inet_ntop, try next address */ error = ERRNO; failf(data, "sa_addr inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); Curl_closesocket(conn, sockfd); return CURLE_OK; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); infof(data, " Trying %s...\n", conn->ip_addr_str); Curl_persistconninfo(conn); if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); nosigpipe(conn, sockfd); Curl_sndbufset(sockfd); if(data->set.tcp_keepalive) tcpkeepalive(data, sockfd); if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, sockfd, CURLSOCKTYPE_IPCXN); if(error == CURL_SOCKOPT_ALREADY_CONNECTED) isconnected = TRUE; else if(error) { Curl_closesocket(conn, sockfd); /* close the socket and bail out */ return CURLE_ABORTED_BY_CALLBACK; } } /* possibly bind the local end to an IP, interface or port */ res = bindlocal(conn, sockfd, addr.family); if(res) { Curl_closesocket(conn, sockfd); /* close socket and bail out */ return res; } /* set socket non-blocking */ curlx_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ if(!isconnected && (conn->socktype == SOCK_STREAM)) { rc = connect(sockfd, &addr.sa_addr, addr.addrlen); if(-1 == rc) error = SOCKERRNO; conn->connecttime = Curl_tvnow(); if(conn->num_addr > 1) Curl_expire(data, conn->timeoutms_per_addr); } else rc = 0; if(-1 == rc) { switch (error) { case EINPROGRESS: case EWOULDBLOCK: #if defined(EAGAIN) #if (EAGAIN) != (EWOULDBLOCK) /* On some platforms EAGAIN and EWOULDBLOCK are the * same value, and on others they are different, hence * the odd #if */ case EAGAIN: #endif #endif rc = waitconnect(conn, sockfd, timeout_ms); if(WAITCONN_ABORTED == rc) { Curl_closesocket(conn, sockfd); return CURLE_ABORTED_BY_CALLBACK; } break; default: /* unknown error, fallthrough and try another address! */ failf(data, "Failed to connect to %s: %s", conn->ip_addr_str, Curl_strerror(conn,error)); data->state.os_errno = error; break; } } /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from connect(). We can be sure of this since connect() cannot return 1. */ if((WAITCONN_TIMEOUT == rc) && (data->state.used_interface == Curl_if_multi)) { /* Timeout when running the multi interface */ *sockp = sockfd; return CURLE_OK; } if(!isconnected) isconnected = verifyconnect(sockfd, &error); if(!rc && isconnected) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); #ifdef ENABLE_IPV6 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE; #endif Curl_updateconninfo(conn, sockfd); *sockp = sockfd; return CURLE_OK; } else if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); else { data->state.os_errno = error; infof(data, "%s\n", Curl_strerror(conn, error)); } /* connect failed or timed out */ Curl_closesocket(conn, sockfd); return CURLE_OK; }
/* main working thread | glock:UNLOCKED */ void* write_worker(void *arg) { uint32_t z1,z2,z3; uint8_t *data; int fd; int i; struct pollfd pfd[2]; uint32_t sent,rcvd; uint8_t recvbuff[21]; uint8_t sendbuff[32]; #ifdef HAVE_WRITEV struct iovec siov[2]; #endif uint8_t pipebuff[1024]; uint8_t *wptr; const uint8_t *rptr; uint32_t reccmd; uint32_t recleng; uint64_t recchunkid; uint32_t recwriteid; uint8_t recstatus; #ifdef WORKER_DEBUG uint32_t partialblocks; uint32_t bytessent; char debugchain[200]; uint32_t cl; #endif const uint8_t *cp,*cpe; uint32_t chainip[10]; uint16_t chainport[10]; uint16_t chainelements; uint16_t chindx; uint32_t ip; uint16_t port; uint32_t srcip; uint64_t mfleng; uint64_t maxwroffset; uint64_t chunkid; uint32_t version; uint32_t nextwriteid; const uint8_t *chain; uint32_t chainsize; const uint8_t *csdata; uint32_t csdatasize; uint8_t westatus; uint8_t wrstatus; int status; uint8_t waitforstatus; uint8_t havedata; struct timeval start,now,lastrcvd,lrdiff; uint8_t cnt; inodedata *id; cblock *cb,*rcb; // inodedata *id; chainelements = 0; (void)arg; for (;;) { for (cnt=0 ; cnt<chainelements ; cnt++) { csdb_writedec(chainip[cnt],chainport[cnt]); } chainelements=0; // get next job queue_get(jqueue,&z1,&z2,&data,&z3); id = (inodedata*)data; pthread_mutex_lock(&glock); if (id->datachainhead) { chindx = id->datachainhead->chindx; } else { syslog(LOG_WARNING,"writeworker got inode with no data to write !!!"); chindx = 0xFFFF; status = EINVAL; // this should never happen, so status is not important - just anything } status = id->status; pthread_mutex_unlock(&glock); if (status) { write_job_end(id,status,0); continue; } // syslog(LOG_NOTICE,"file: %"PRIu32", index: %"PRIu16" - debug1",id->inode,chindx); // get chunk data from master wrstatus = fs_writechunk(id->inode,chindx,&mfleng,&chunkid,&version,&csdata,&csdatasize); if (wrstatus!=STATUS_OK) { syslog(LOG_WARNING,"file: %"PRIu32", index: %"PRIu16" - fs_writechunk returns status %d",id->inode,chindx,wrstatus); if (wrstatus!=ERROR_LOCKED) { if (wrstatus==ERROR_ENOENT) { write_job_end(id,EBADF,0); } else if (wrstatus==ERROR_QUOTA) { write_job_end(id,EDQUOT,0); } else if (wrstatus==ERROR_NOSPACE) { write_job_end(id,ENOSPC,0); } else { id->trycnt++; if (id->trycnt>=maxretries) { if (wrstatus==ERROR_NOCHUNKSERVERS) { write_job_end(id,ENOSPC,0); } else { write_job_end(id,EIO,0); } } else { write_delayed_enqueue(id,1+(id->trycnt<30)?(id->trycnt/3):10); } } } else { write_delayed_enqueue(id,1+(id->trycnt<30)?(id->trycnt/3):10); } continue; // get next job } if (csdata==NULL || csdatasize==0) { syslog(LOG_WARNING,"file: %"PRIu32", index: %"PRIu16", chunk: %"PRIu64", version: %"PRIu32" - there are no valid copies",id->inode,chindx,chunkid,version); id->trycnt+=6; if (id->trycnt>=maxretries) { write_job_end(id,ENXIO,0); } else { write_delayed_enqueue(id,60); } continue; } cp = csdata; cpe = csdata+csdatasize; while (cp<cpe && chainelements<10) { chainip[chainelements] = get32bit(&cp); chainport[chainelements] = get16bit(&cp); csdb_writeinc(chainip[chainelements],chainport[chainelements]); chainelements++; } chain = csdata; ip = get32bit(&chain); port = get16bit(&chain); chainsize = csdatasize-6; gettimeofday(&start,NULL); /* if (csdatasize>CSDATARESERVE) { csdatasize = CSDATARESERVE; } memcpy(wrec->csdata,csdata,csdatasize); wrec->csdatasize=csdatasize; while (csdatasize>=6) { tmpip = get32bit(&csdata); tmpport = get16bit(&csdata); csdatasize-=6; csdb_writeinc(tmpip,tmpport); } */ // make connection to cs srcip = fs_getsrcip(); cnt=5; while (cnt>0) { fd = tcpsocket(); if (fd<0) { syslog(LOG_WARNING,"can't create tcp socket: %m"); cnt=0; } if (srcip) { if (tcpnumbind(fd,srcip,0)<0) { syslog(LOG_WARNING,"can't bind socket to given ip: %m"); tcpclose(fd); fd=-1; break; } } if (tcpnumtoconnect(fd,ip,port,200)<0) { cnt--; if (cnt==0) { syslog(LOG_WARNING,"can't connect to (%08"PRIX32":%"PRIu16"): %m",ip,port); } tcpclose(fd); fd=-1; } else { cnt=0; } } if (fd<0) { fs_writeend(chunkid,id->inode,0); id->trycnt++; if (id->trycnt>=maxretries) { write_job_end(id,EIO,0); } else { write_delayed_enqueue(id,1+(id->trycnt<30)?(id->trycnt/3):10); } continue; } if (tcpnodelay(fd)<0) { syslog(LOG_WARNING,"can't set TCP_NODELAY: %m"); } #ifdef WORKER_DEBUG partialblocks=0; bytessent=0; #endif nextwriteid=1; pfd[0].fd = fd; pfd[1].fd = id->pipe[0]; rcvd = 0; sent = 0; waitforstatus=1; havedata=1; wptr = sendbuff; put32bit(&wptr,CUTOCS_WRITE); put32bit(&wptr,12+chainsize); put64bit(&wptr,chunkid); put32bit(&wptr,version); // debug: syslog(LOG_NOTICE,"writeworker: init packet prepared"); cb = NULL; status = 0; wrstatus = STATUS_OK; lastrcvd.tv_sec = 0; do { gettimeofday(&now,NULL); if (lastrcvd.tv_sec==0) { lastrcvd = now; } else { lrdiff = now; if (lrdiff.tv_usec<lastrcvd.tv_usec) { lrdiff.tv_sec--; lrdiff.tv_usec+=1000000; } lrdiff.tv_sec -= lastrcvd.tv_sec; lrdiff.tv_usec -= lastrcvd.tv_usec; if (lrdiff.tv_sec>=2) { syslog(LOG_WARNING,"file: %"PRIu32", index: %"PRIu16", chunk: %"PRIu64", version: %"PRIu32" - writeworker: connection with (%08"PRIX32":%"PRIu16") was timed out (unfinished writes: %"PRIu8"; try counter: %"PRIu32")",id->inode,chindx,chunkid,version,ip,port,waitforstatus,id->trycnt+1); break; } } if (now.tv_usec<start.tv_usec) { now.tv_sec--; now.tv_usec+=1000000; } now.tv_sec -= start.tv_sec; now.tv_usec -= start.tv_usec; if (havedata==0 && now.tv_sec<5 && waitforstatus<5) { pthread_mutex_lock(&glock); if (cb==NULL) { if (id->datachainhead) { if (id->datachainhead->to-id->datachainhead->from==65536 || waitforstatus<=1) { cb = id->datachainhead; havedata=1; } } } else { if (cb->next) { if (cb->next->chindx==chindx) { if (cb->next->to-cb->next->from==65536 || waitforstatus<=1) { cb = cb->next; havedata=1; } } } else { id->waitingworker=1; } } if (havedata==1) { cb->writeid = nextwriteid++; // debug: syslog(LOG_NOTICE,"writeworker: data packet prepared (writeid:%"PRIu32",pos:%"PRIu16")",cb->writeid,cb->pos); waitforstatus++; wptr = sendbuff; put32bit(&wptr,CUTOCS_WRITE_DATA); put32bit(&wptr,24+(cb->to-cb->from)); put64bit(&wptr,chunkid); put32bit(&wptr,cb->writeid); put16bit(&wptr,cb->pos); put16bit(&wptr,cb->from); put32bit(&wptr,cb->to-cb->from); put32bit(&wptr,mycrc32(0,cb->data+cb->from,cb->to-cb->from)); #ifdef WORKER_DEBUG if (cb->to-cb->from<65536) { partialblocks++; } bytessent+=(cb->to-cb->from); #endif sent=0; } pthread_mutex_unlock(&glock); } pfd[0].events = POLLIN | (havedata?POLLOUT:0); pfd[0].revents = 0; pfd[1].events = POLLIN; pfd[1].revents = 0; if (poll(pfd,2,100)<0) { /* correct timeout - in msec */ syslog(LOG_WARNING,"writeworker: poll error: %m"); status=EIO; break; } if (pfd[1].revents&POLLIN) { // used just to break poll - so just read all data from pipe to empty it i = read(id->pipe[0],pipebuff,1024); } if (pfd[0].revents&POLLIN) { i = read(fd,recvbuff+rcvd,21-rcvd); if (i==0) { // connection reset by peer ,读取文件头错误 syslog(LOG_WARNING,"file: %"PRIu32", index: %"PRIu16", chunk: %"PRIu64", version: %"PRIu32" - writeworker: connection with (%08"PRIX32":%"PRIu16") was reset by peer (unfinished writes: %"PRIu8"; try counter: %"PRIu32")",id->inode,chindx,chunkid,version,ip,port,waitforstatus,id->trycnt+1); status=EIO; break; } gettimeofday(&lastrcvd,NULL); rcvd+=i; if (rcvd==21) { rptr = recvbuff; reccmd = get32bit(&rptr); recleng = get32bit(&rptr); recchunkid = get64bit(&rptr); recwriteid = get32bit(&rptr); recstatus = get8bit(&rptr); if (reccmd!=CSTOCU_WRITE_STATUS || recleng!=13) { syslog(LOG_WARNING,"writeworker: got unrecognized packet from chunkserver (cmd:%"PRIu32",leng:%"PRIu32")",reccmd,recleng); status=EIO; break; } if (recchunkid!=chunkid) { syslog(LOG_WARNING,"writeworker: got unexpected packet (expected chunkdid:%"PRIu64",packet chunkid:%"PRIu64")",chunkid,recchunkid); status=EIO; break; } if (recstatus!=STATUS_OK) { syslog(LOG_WARNING,"writeworker: write error: %"PRIu8,recstatus); wrstatus=recstatus; break; } // debug: syslog(LOG_NOTICE,"writeworker: received status ok for writeid:%"PRIu32,recwriteid); if (recwriteid>0) { pthread_mutex_lock(&glock); for (rcb = id->datachainhead ; rcb && rcb->writeid!=recwriteid ; rcb=rcb->next) {} if (rcb==NULL) { syslog(LOG_WARNING,"writeworker: got unexpected status (writeid:%"PRIu32")",recwriteid); pthread_mutex_unlock(&glock); status=EIO; break; } if (rcb==cb) { // current block,cb为当前块儿指针 // debug: syslog(LOG_NOTICE,"writeworker: received status for current block"); if (havedata) { // got status ok before all data had been sent - error syslog(LOG_WARNING,"writeworker: got status OK before all data have been sent"); pthread_mutex_unlock(&glock); status=EIO; break; } else { cb = NULL; } } if (rcb->prev) {//将rcb所指块儿从链表中取出 rcb->prev->next = rcb->next; } else { id->datachainhead = rcb->next; } if (rcb->next) { rcb->next->prev = rcb->prev; } else { id->datachaintail = rcb->prev; } maxwroffset = (((uint64_t)(chindx))<<26)+(((uint32_t)(rcb->pos))<<16)+rcb->to; if (maxwroffset>mfleng) { mfleng=maxwroffset; } write_cb_release(rcb);// id->cacheblocks--; if (id->cachewaiting>0) { pthread_cond_broadcast(&(id->cachecond)); } pthread_mutex_unlock(&glock); } waitforstatus--; rcvd=0; } } if (havedata && (pfd[0].revents&POLLOUT)) { if (cb==NULL) { // havedata==1 && cb==NULL means sending first packet (CUTOCS_WRITE) if (sent<20) { #ifdef HAVE_WRITEV //将多个数据存储在一起,将驻留在两个或更多的不连接的缓冲区中的数据一次写出去 if (chainsize>0) { siov[0].iov_base = sendbuff+sent; siov[0].iov_len = 20-sent; siov[1].iov_base = (char*)chain; // discard const (safe - because it's used in writev) siov[1].iov_len = chainsize; i = writev(fd,siov,2); } else { #endif i = write(fd,sendbuff+sent,20-sent); #ifdef HAVE_WRITEV } #endif } else { i = write(fd,chain+(sent-20),chainsize-(sent-20)); } if (i<0) { syslog(LOG_WARNING,"file: %"PRIu32", index: %"PRIu16", chunk: %"PRIu64", version: %"PRIu32" - writeworker: connection with (%08"PRIX32":%"PRIu16") was reset by peer (unfinished writes: %"PRIu8"; try counter: %"PRIu32")",id->inode,chindx,chunkid,version,ip,port,waitforstatus,id->trycnt+1); status=EIO; break; } sent+=i; if (sent==20+chainsize) { havedata=0; } } else { if (sent<32) { #ifdef HAVE_WRITEV siov[0].iov_base = sendbuff+sent; siov[0].iov_len = 32-sent; siov[1].iov_base = cb->data+cb->from; siov[1].iov_len = cb->to-cb->from; i = writev(fd,siov,2); #else i = write(fd,sendbuff+sent,32-sent); #endif } else { i = write(fd,cb->data+cb->from+(sent-32),cb->to-cb->from-(sent-32)); } if (i<0) { syslog(LOG_WARNING,"file: %"PRIu32", index: %"PRIu16", chunk: %"PRIu64", version: %"PRIu32" - writeworker: connection with (%08"PRIX32":%"PRIu16") was reset by peer (unfinished writes: %"PRIu8"; try counter: %"PRIu32")",id->inode,chindx,chunkid,version,ip,port,waitforstatus,id->trycnt+1); status=EIO; break; } sent+=i; if (sent==32+cb->to-cb->from) { havedata=0; } } } } while (waitforstatus>0 && now.tv_sec<10);//////////////////// id->waitingworker=0; tcpclose(fd); #ifdef WORKER_DEBUG gettimeofday(&now,NULL); if (now.tv_usec<start.tv_usec) { now.tv_sec--; now.tv_usec+=1000000; } now.tv_sec -= start.tv_sec; now.tv_usec -= start.tv_usec; cl=0; for (cnt=0 ; cnt<chainelements ; cnt++) { cl+=snprintf(debugchain+cl,200-cl,"%u.%u.%u.%u:%u->",(chainip[cnt]>>24)&255,(chainip[cnt]>>16)&255,(chainip[cnt]>>8)&255,chainip[cnt]&255,chainport[cnt]); } if (cl>=2) { debugchain[cl-2]='\0'; } syslog(LOG_NOTICE,"worker %lu sent %"PRIu32" blocks (%"PRIu32" partial) of chunk %016"PRIX64"_%08"PRIX32", received status for %"PRIu32" blocks (%"PRIu32" lost), bw: %.6lfMB ( %"PRIu32" B / %.0lf us ), chain: %s",(unsigned long)arg,nextwriteid-1,partialblocks,chunkid,version,nextwriteid-1-waitforstatus,waitforstatus,(double)bytessent/((double)(now.tv_sec)*1000000+(double)(now.tv_usec)),bytessent,((double)(now.tv_sec)*1000000+(double)(now.tv_usec)),debugchain); #endif for (cnt=0 ; cnt<10 ; cnt++) { westatus = fs_writeend(chunkid,id->inode,mfleng); if (westatus!=STATUS_OK) { usleep(100000+(10000<<cnt)); } else { break; } } if (westatus!=STATUS_OK) { write_job_end(id,ENXIO,0); } else if (status!=0 || wrstatus!=STATUS_OK) { if (wrstatus!=STATUS_OK) { // convert MFS status to OS errno if (wrstatus==ERROR_NOSPACE) { status=ENOSPC; } else { status=EIO; } } id->trycnt++; if (id->trycnt>=maxretries) { write_job_end(id,status,0); } else { write_job_end(id,0,1+(id->trycnt<30)?(id->trycnt/3):10); } } else { read_inode_ops(id->inode); write_job_end(id,0,0); } } }
/* srcs: srccnt * (chunkid:64 version:32 ip:32 port:16) */ uint8_t replicate(uint64_t chunkid,uint32_t version,const uint32_t xormasks[4],uint8_t srccnt,const uint8_t *srcs) { replication r; uint8_t status,i,j,vbuffs,first; uint16_t b,blocks; uint32_t xcrc[4],crc; uint32_t codeindex,codeword; uint8_t *wptr; const uint8_t *rptr; int s; if (srccnt==0) { return ERROR_EINVAL; } // syslog(LOG_NOTICE,"replication begin (chunkid:%08"PRIX64",version:%04"PRIX32",srccnt:%"PRIu8")",chunkid,version,srccnt); pthread_mutex_lock(&statslock); stats_repl++; pthread_mutex_unlock(&statslock); // init replication structure r.chunkid = chunkid; r.version = version; r.srccnt = 0; r.created = 0; r.opened = 0; r.fds = malloc(sizeof(struct pollfd)*srccnt); passert(r.fds); r.repsources = malloc(sizeof(repsrc)*srccnt); passert(r.repsources); if (srccnt>1) { r.xorbuff = malloc(MFSBLOCKSIZE+4); passert(r.xorbuff); } else { r.xorbuff = NULL; } // create chunk status = hdd_create(chunkid,0); if (status!=STATUS_OK) { syslog(LOG_NOTICE,"replicator: hdd_create status: %s",mfsstrerr(status)); rep_cleanup(&r); return status; } r.created = 1; // init sources r.srccnt = srccnt; for (i=0 ; i<srccnt ; i++) { r.repsources[i].chunkid = get64bit(&srcs); r.repsources[i].version = get32bit(&srcs); r.repsources[i].ip = get32bit(&srcs); r.repsources[i].port = get16bit(&srcs); r.repsources[i].sock = -1; r.repsources[i].packet = NULL; } // connect for (i=0 ; i<srccnt ; i++) { s = tcpsocket(); if (s<0) { mfs_errlog_silent(LOG_NOTICE,"replicator: socket error"); rep_cleanup(&r); return ERROR_CANTCONNECT; } r.repsources[i].sock = s; r.fds[i].fd = s; if (tcpnonblock(s)<0) { mfs_errlog_silent(LOG_NOTICE,"replicator: nonblock error"); rep_cleanup(&r); return ERROR_CANTCONNECT; } s = tcpnumconnect(s,r.repsources[i].ip,r.repsources[i].port); if (s<0) { mfs_errlog_silent(LOG_NOTICE,"replicator: connect error"); rep_cleanup(&r); return ERROR_CANTCONNECT; } if (s==0) { r.repsources[i].mode = IDLE; } else { r.repsources[i].mode = CONNECTING; } } if (rep_wait_for_connection(&r,CONNMSECTO)<0) { rep_cleanup(&r); return ERROR_CANTCONNECT; } // disable Nagle for (i=0 ; i<srccnt ; i++) { tcpnodelay(r.repsources[i].sock); } // open chunk status = hdd_open(chunkid,0); if (status!=STATUS_OK) { syslog(LOG_NOTICE,"replicator: hdd_open status: %s",mfsstrerr(status)); rep_cleanup(&r); return status; } r.opened = 1; // get block numbers for (i=0 ; i<srccnt ; i++) { wptr = rep_create_packet(r.repsources+i,ANTOCS_GET_CHUNK_BLOCKS,8+4); if (wptr==NULL) { syslog(LOG_NOTICE,"replicator: out of memory"); rep_cleanup(&r); return ERROR_OUTOFMEMORY; } put64bit(&wptr,r.repsources[i].chunkid); put32bit(&wptr,r.repsources[i].version); } // send packet if (rep_send_all_packets(&r,SENDMSECTO)<0) { rep_cleanup(&r); return ERROR_DISCONNECTED; } // receive answers for (i=0 ; i<srccnt ; i++) { r.repsources[i].mode = HEADER; r.repsources[i].startptr = r.repsources[i].hdrbuff; r.repsources[i].bytesleft = 8; } if (rep_receive_all_packets(&r,RECVMSECTO)<0) { rep_cleanup(&r); return ERROR_DISCONNECTED; } // get # of blocks blocks = 0; for (i=0 ; i<srccnt ; i++) { uint32_t type,size; uint64_t pchid; uint32_t pver; uint16_t pblocks; uint8_t pstatus; uint32_t ip; rptr = r.repsources[i].hdrbuff; type = get32bit(&rptr); size = get32bit(&rptr); rptr = r.repsources[i].packet; ip = r.repsources[i].ip; if (rptr==NULL || type!=CSTOAN_CHUNK_BLOCKS || size!=15) { syslog(LOG_WARNING,"replicator,get # of blocks: got wrong answer (type:0x%08"PRIX32"/size:0x%08"PRIX32") from (%u.%u.%u.%u:%04"PRIX16")",type,size,(ip>>24)&0xFF,(ip>>16)&0xFF,(ip>>8)&0xFF,ip&0xFF,r.repsources[i].port); rep_cleanup(&r); return ERROR_DISCONNECTED; } pchid = get64bit(&rptr); pver = get32bit(&rptr); pblocks = get16bit(&rptr); pstatus = get8bit(&rptr); if (pchid!=r.repsources[i].chunkid) { syslog(LOG_WARNING,"replicator,get # of blocks: got wrong answer (chunk_status:chunkid:%"PRIX64"/%"PRIX64") from (%u.%u.%u.%u:%04"PRIX16")",pchid,r.repsources[i].chunkid,(ip>>24)&0xFF,(ip>>16)&0xFF,(ip>>8)&0xFF,ip&0xFF,r.repsources[i].port); rep_cleanup(&r); return ERROR_WRONGCHUNKID; }
void matomlserv_serve(struct pollfd *pdesc) { uint32_t now=main_time(); matomlserventry *eptr,**kptr; packetstruct *pptr,*paptr; int ns; static uint64_t lastaction = 0; uint64_t unow; uint32_t timeoutadd; if (lastaction==0) { lastaction = main_precise_utime(); } if (lsockpdescpos>=0 && (pdesc[lsockpdescpos].revents & POLLIN)) { ns=tcpaccept(lsock); if (ns<0) { mfs_errlog_silent(LOG_NOTICE,"Master<->ML socket: accept error"); } else { tcpnonblock(ns); tcpnodelay(ns); eptr = malloc(sizeof(matomlserventry)); passert(eptr); eptr->next = matomlservhead; matomlservhead = eptr; eptr->sock = ns; eptr->pdescpos = -1; eptr->mode = HEADER; eptr->lastread = now; eptr->lastwrite = now; eptr->inputpacket.next = NULL; eptr->inputpacket.bytesleft = 8; eptr->inputpacket.startptr = eptr->hdrbuff; eptr->inputpacket.packet = NULL; eptr->outputhead = NULL; eptr->outputtail = &(eptr->outputhead); eptr->timeout = 10; tcpgetpeer(eptr->sock,&(eptr->servip),NULL); eptr->servstrip = matomlserv_makestrip(eptr->servip); eptr->version=0; eptr->metafd=-1; eptr->chain1fd=-1; eptr->chain2fd=-1; eptr->logindex=-1; eptr->logf=NULL; eptr->currentversion=0; } } // read for (eptr=matomlservhead ; eptr ; eptr=eptr->next) { if (eptr->pdescpos>=0) { if (pdesc[eptr->pdescpos].revents & (POLLERR|POLLHUP)) { eptr->mode = KILL; } if ((pdesc[eptr->pdescpos].revents & POLLIN) && eptr->mode!=KILL) { eptr->lastread = now; matomlserv_read(eptr); } } } // timeout fix unow = main_precise_utime(); timeoutadd = (unow-lastaction)/1000000; if (timeoutadd) { for (eptr=matomlservhead ; eptr ; eptr=eptr->next) { eptr->lastread += timeoutadd; } } lastaction = unow; // write for (eptr=matomlservhead ; eptr ; eptr=eptr->next) { if ((uint32_t)(eptr->lastwrite+(eptr->timeout/3))<(uint32_t)now && eptr->outputhead==NULL) { matomlserv_createpacket(eptr,ANTOAN_NOP,0); } if (eptr->pdescpos>=0) { if ((((pdesc[eptr->pdescpos].events & POLLOUT)==0 && (eptr->outputhead)) || (pdesc[eptr->pdescpos].revents & POLLOUT)) && eptr->mode!=KILL) { eptr->lastwrite = now; matomlserv_write(eptr); } if (eptr->mode!=KILL && eptr->logf && eptr->outputhead==NULL) { matomlserv_send_old_changes(eptr, eptr->currentversion); } } if ((uint32_t)(eptr->lastread+eptr->timeout)<(uint32_t)now) { eptr->mode = KILL; } } // close kptr = &matomlservhead; while ((eptr=*kptr)) { if (eptr->mode == KILL) { matomlserv_beforeclose(eptr); tcpclose(eptr->sock); if (eptr->inputpacket.packet) { free(eptr->inputpacket.packet); } pptr = eptr->outputhead; while (pptr) { if (pptr->packet) { free(pptr->packet); } paptr = pptr; pptr = pptr->next; free(paptr); } if (eptr->servstrip) { free(eptr->servstrip); } *kptr = eptr->next; free(eptr); } else { kptr = &(eptr->next); } } }
/* * singleipconnect() * * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to * CURL_SOCKET_BAD. Other errors will however return proper errors. * * singleipconnect() connects to the given IP only, and it may return without * having connected if used from the multi interface. */ static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, long timeout_ms, curl_socket_t *sockp, bool *connected) { struct Curl_sockaddr_ex addr; int rc; int error; bool isconnected = FALSE; struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res = CURLE_OK; #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; #endif *sockp = CURL_SOCKET_BAD; /* * The Curl_sockaddr_ex structure is basically libcurl's external API * curl_sockaddr structure with enough space available to directly hold * any protocol-specific address structures. The variable declared here * will be used to pass / receive data to/from the fopensocket callback * if this has been set, before that, it is initialized from parameters. */ addr.family = ai->ai_family; addr.socktype = conn->socktype; addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; addr.addrlen = ai->ai_addrlen; if(addr.addrlen > sizeof(struct Curl_sockaddr_storage)) addr.addrlen = sizeof(struct Curl_sockaddr_storage); memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen); *connected = FALSE; /* default is not connected */ if(data->set.fopensocket) /* * If the opensocket callback is set, all the destination address * information is passed to the callback. Depending on this information the * callback may opt to abort the connection, this is indicated returning * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When * the callback returns a valid socket the destination address information * might have been changed and this 'new' address will actually be used * here to connect. */ sockfd = data->set.fopensocket(data->set.opensocket_client, CURLSOCKTYPE_IPCXN, (struct curl_sockaddr *)&addr); else /* opensocket callback not set, so simply create the socket now */ sockfd = socket(addr.family, addr.socktype, addr.protocol); if(sockfd == CURL_SOCKET_BAD) /* no socket, no connection */ return CURLE_OK; #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) if (conn->scope && (addr.family == AF_INET6)) sa6->sin6_scope_id = conn->scope; #endif /* store remote address and port used in this connection attempt */ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, conn->primary_ip, &conn->primary_port)) { /* malformed address or bug in inet_ntop, try next address */ error = ERRNO; failf(data, "sa_addr inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); sclose(sockfd); return CURLE_OK; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); infof(data, " Trying %s... ", conn->ip_addr_str); Curl_persistconninfo(conn); #ifdef ENABLE_IPV6 if(addr.family == AF_INET6) conn->bits.ipv6 = TRUE; #endif if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); nosigpipe(conn, sockfd); Curl_sndbufset(sockfd); if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, sockfd, CURLSOCKTYPE_IPCXN); if(error == CURL_SOCKOPT_ALREADY_CONNECTED) isconnected = TRUE; else if(error) { sclose(sockfd); /* close the socket and bail out */ return CURLE_ABORTED_BY_CALLBACK; } } /* possibly bind the local end to an IP, interface or port */ res = bindlocal(conn, sockfd, addr.family); if(res) { sclose(sockfd); /* close socket and bail out */ return res; } /* set socket non-blocking */ curlx_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ if(!isconnected && (conn->socktype == SOCK_STREAM)) { rc = connect(sockfd, &addr.sa_addr, addr.addrlen); conn->connecttime = Curl_tvnow(); if(conn->num_addr > 1) Curl_expire(data, conn->timeoutms_per_addr); } else rc = 0; if(-1 == rc) { error = SOCKERRNO; switch (error) { case EINPROGRESS: case EWOULDBLOCK: #if defined(EAGAIN) #if (EAGAIN) != (EWOULDBLOCK) /* On some platforms EAGAIN and EWOULDBLOCK are the * same value, and on others they are different, hence * the odd #if */ case EAGAIN: #endif #endif rc = waitconnect(conn, sockfd, timeout_ms); if(WAITCONN_ABORTED == rc) { sclose(sockfd); return CURLE_ABORTED_BY_CALLBACK; } break; default: /* unknown error, fallthrough and try another address! */ failf(data, "Failed to connect to %s: %s", conn->ip_addr_str, Curl_strerror(conn,error)); data->state.os_errno = error; break; } } /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from connect(). We can be sure of this since connect() cannot return 1. */ if((WAITCONN_TIMEOUT == rc) && (data->state.used_interface == Curl_if_multi)) { /* Timeout when running the multi interface */ *sockp = sockfd; return CURLE_OK; } if(!isconnected) isconnected = verifyconnect(sockfd, &error); if(!rc && isconnected) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); Curl_updateconninfo(conn, sockfd); *sockp = sockfd; return CURLE_OK; } else if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); else { data->state.os_errno = error; infof(data, "%s\n", Curl_strerror(conn, error)); } /* connect failed or timed out */ sclose(sockfd); return CURLE_OK; }
void masterconn_serve(int epoll_fd,int count,struct epoll_event *pdesc) { //uint32_t now=main_time(); serventry *weptr = NULL,*eptr = NULL; int ns; int ret; struct epoll_event ev; if(ismaster()) { return; } weptr = (serventry *)pdesc[count].data.ptr; if ((weptr->listen_sock == 1) && (pdesc[count].events & EPOLLIN) && (weptr->mode != KILL)) { ns = tcpaccept(lsock); if (ns<0) { MFSLOG(LOG_INFO,"master sync thread<->shadow master socket: accept error: %m"); } else { tcpnonblock(ns); tcpnodelay(ns); master_serve = (serventry *)malloc(sizeof(serventry)); eptr = master_serve; eptr->sock = ns; eptr->mode = HEADER; eptr->lastread = eptr->lastwrite = get_current_time(); eptr->inputpacket.next = NULL; eptr->inputpacket.bytesleft = 8; eptr->inputpacket.startptr = eptr->hdrbuff; eptr->inputpacket.packet = NULL; eptr->outputhead = NULL; eptr->outputtail = &(eptr->outputhead); eptr->downloading = 0; eptr->metafd=-1; eptr->logfd=NULL; eptr->listen_sock = 0; eptr->connection = 3; ev.data.ptr = eptr; ev.events = EPOLLIN; ret = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,ns,&ev); if (ret < 0) { MFSLOG(LOG_NOTICE,"add epoll fail"); } } } if (weptr->listen_sock == 0) { if (weptr->mode == CONNECTING) { if (pdesc[count].events & (EPOLLHUP | EPOLLERR)) { masterconn_connecttest(weptr); } if (pdesc[count].events & EPOLLOUT) { masterconn_connecttest(weptr); } } else { if ((pdesc[count].events & (EPOLLHUP | EPOLLERR)) && (weptr->mode != KILL)) { MFSLOG(LOG_NOTICE, "set to NULL"); weptr->mode = KILL; } if ((weptr->mode==HEADER || weptr->mode==DATA) && (pdesc[count].events & EPOLLIN)) { // FD_ISSET(eptr->sock,rset)) { masterconn_read(weptr); weptr->lastread = get_current_time(); } if ((weptr->mode==HEADER || weptr->mode==DATA) && (pdesc[count].events & EPOLLOUT)) { // FD_ISSET(eptr->sock,wset)) { masterconn_write(weptr); weptr->lastwrite = get_current_time(); } if ((weptr->mode==HEADER || weptr->mode==DATA) && weptr->lastread+Timeout<get_current_time()) { MFSLOG(LOG_NOTICE, "set to NULL"); weptr->mode = KILL; } if ((weptr->mode==HEADER || weptr->mode==DATA) && weptr->lastwrite+5<get_current_time() && weptr->outputhead==NULL) { masterconn_createpacket(weptr,ANTOAN_NOP,0); } } } }