📄 server.c
字号:
if (!(c = conn_create(csocket,usocket,raddr,rport,addr_get_ip(curr_laddr),addr_get_port(curr_laddr),ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to create new connection (closing connection)",csocket); psock_close(csocket); return -1; } if (conn_add_fdwatch(c, handle_tcp) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to add socket to fdwatch pool (max connections?)",csocket); conn_set_state(c,conn_state_destroy); return -1; } eventlog(eventlog_level_debug,__FUNCTION__,"[%d] client connected to a %s listening address",csocket,laddr_type_get_str(laddr_info->type)); switch (laddr_info->type) { case laddr_type_irc: conn_set_class(c,conn_class_irc); conn_set_state(c,conn_state_connected); break; case laddr_type_wol: conn_set_class(c,conn_class_wol); conn_set_state(c,conn_state_connected); break; case laddr_type_w3route: conn_set_class(c,conn_class_w3route); conn_set_state(c,conn_state_connected); break; case laddr_type_telnet: conn_set_class(c,conn_class_telnet); conn_set_state(c,conn_state_connected); break; case laddr_type_bnet: { /* add a timer to close stale connections */ int delay; t_timer_data data; data.p = NULL; delay = prefs_get_initkill_timer(); if (delay) timerlist_add_timer(c,time(NULL)+delay,conn_shutdown,data); } default: /* We have to wait for an initial "magic" byte on bnet connections to * tell us exactly what connection class we are dealing with. */ break; } } return 0;}static int sd_udpinput(t_addr * const curr_laddr, t_laddr_info const * laddr_info, int ssocket, int usocket){ int err; psock_t_socklen errlen; t_packet * upacket; err = 0; errlen = sizeof(err); if (psock_getsockopt(usocket,PSOCK_SOL_SOCKET,PSOCK_SO_ERROR,&err,&errlen)<0) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to read socket error (psock_getsockopt: %s)",usocket,pstrerror(psock_errno())); return -1; } if (errlen && err) /* if it was an error, there is no packet to read */ { eventlog(eventlog_level_error,__FUNCTION__,"[%d] async UDP socket error notification (psock_getsockopt: %s)",usocket,pstrerror(err)); return -1; } if (!(upacket = packet_create(packet_class_udp))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); return -1; } { struct sockaddr_in fromaddr; psock_t_socklen fromlen; int len; fromlen = sizeof(fromaddr); if ((len = psock_recvfrom(usocket,packet_get_raw_data_build(upacket,0),MAX_PACKET_SIZE,0,(struct sockaddr *)&fromaddr,&fromlen))<0) { if (#ifdef PSOCK_EINTR psock_errno()!=PSOCK_EINTR &&#endif#ifdef PSOCK_EAGAIN psock_errno()!=PSOCK_EAGAIN &&#endif#ifdef PSOCK_EWOULDBLOCK psock_errno()!=PSOCK_EWOULDBLOCK &&#endif#ifdef PSOCK_ECONNRESET psock_errno()!=PSOCK_ECONNRESET && /* this is a win2k/winxp issue * their socket implementation returns this value * although it shouldn't */#endif 1) eventlog(eventlog_level_error,__FUNCTION__,"could not recv UDP datagram (psock_recvfrom: %s)",pstrerror(psock_errno())); packet_del_ref(upacket); return -1; } if (fromaddr.sin_family!=PSOCK_AF_INET) { eventlog(eventlog_level_error,__FUNCTION__,"got UDP datagram with bad address family %d",(int)fromaddr.sin_family); packet_del_ref(upacket); return -1; } packet_set_size(upacket,len); if (hexstrm) { char tempa[32]; if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa))) strcpy(tempa,"x.x.x.x:x"); fprintf(hexstrm,"%d: recv class=%s[0x%02x] type=%s[0x%04x] from=%s to=%s length=%u\n", usocket, packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket), packet_get_type_str(upacket,packet_dir_from_client),packet_get_type(upacket), addr_num_to_addr_str(ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port)), tempa, packet_get_size(upacket)); hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket)); } handle_udp_packet(usocket,ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port),upacket); packet_del_ref(upacket); } return 0;}static int sd_tcpinput(t_connection * c){ unsigned int currsize; t_packet * packet; int csocket = conn_get_socket(c); currsize = conn_get_in_size(c); if (!conn_get_in_queue(c)) { switch (conn_get_class(c)) { case conn_class_init: if (!(packet = packet_create(packet_class_init))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate init packet for input"); return -1; } break; case conn_class_d2cs_bnetd: if (!(packet = packet_create(packet_class_d2cs_bnetd))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate d2cs_bnetd packet"); return -1; } break; case conn_class_bnet: if (!(packet = packet_create(packet_class_bnet))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate bnet packet for input"); return -1; } break; case conn_class_file: switch(conn_get_state(c)) { case conn_state_pending_raw: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); return -1; } packet_set_size(packet, sizeof(t_client_file_req3)); break; default: if (!(packet = packet_create(packet_class_file))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate file packet for input"); return -1; } break; } break; case conn_class_bot: case conn_class_irc: case conn_class_wol: case conn_class_telnet: if (!(packet = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input"); return -1; } packet_set_size(packet,1); /* start by only reading one char */ break; case conn_class_w3route: if (!(packet = packet_create(packet_class_w3route))) { eventlog(eventlog_level_error,__FUNCTION__,"could not allocate w3route packet for input"); return -1; } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection has bad class (closing connection)",conn_get_socket(c)); /* marking connection as "destroyed", memory will be freed later */ conn_set_state(c, conn_state_destroy); return -2; } conn_put_in_queue(c,packet); currsize = 0; } packet = conn_get_in_queue(c); switch (net_recv_packet(csocket,packet,&currsize)) { case -1: eventlog(eventlog_level_debug,__FUNCTION__,"[%d] read FAILED (closing connection)",conn_get_socket(c)); /* marking connection as "destroyed", memory will be freed later */ conn_set_state(c, conn_state_destroy); return -2; case 0: /* still working on it */ /* eventlog(eventlog_level_debug,__FUNCTION__,"[%d] still reading \"%s\" packet (%u of %u bytes so far)",conn_get_socket(c),packet_get_class_str(packet),conn_get_in_size(c),packet_get_size(packet)); */ conn_set_in_size(c,currsize); break; case 1: /* done reading */ switch (conn_get_class(c)) { case conn_class_bot: case conn_class_telnet: if (currsize<MAX_PACKET_SIZE) /* if we overflow, we can't wait for the end of the line. handle_*_packet() should take care of it */ { char const * const temp=packet_get_raw_data_const(packet,0); if ((temp[currsize-1]=='\003')||(temp[currsize-1]=='\004')) { /* we have to ignore these special characters, since * some bots even send them after login (eg. UltimateBot) */ currsize--; break; } if (temp[currsize-1]!='\r' && temp[currsize-1]!='\n') { conn_set_in_size(c,currsize); packet_set_size(packet,currsize+1); break; /* no end of line, get another char */ } } /* got a complete line or overflow... fall through */ default: conn_put_in_queue(c,NULL); if (hexstrm) { fprintf(hexstrm,"%d: recv class=%s[0x%02x] type=%s[0x%04x] length=%u\n", csocket, packet_get_class_str(packet),(unsigned int)packet_get_class(packet), packet_get_type_str(packet,packet_dir_from_client),packet_get_type(packet), packet_get_size(packet)); hexdump(hexstrm,packet_get_raw_data_const(packet,0),packet_get_size(packet)); } if (conn_get_class(c)==conn_class_bot || conn_get_class(c)==conn_class_telnet) /* NUL terminate the line to make life easier */ { char * const temp=packet_get_raw_data(packet,0); if (temp[currsize-1]=='\r' || temp[currsize-1]=='\n') temp[currsize-1] = '\0'; /* have to do it here instead of above so everything is intact for the hexdump */ } { int ret; switch (conn_get_class(c)) { case conn_class_init: ret = handle_init_packet(c,packet); break; case conn_class_bnet: ret = handle_bnet_packet(c,packet); break; case conn_class_d2cs_bnetd: ret = handle_d2cs_packet(c,packet); break; case conn_class_bot: ret = handle_bot_packet(c,packet); break; case conn_class_telnet: ret = handle_telnet_packet(c,packet); break; case conn_class_file: ret = handle_file_packet(c,packet); break; case conn_class_irc: case conn_class_wol: ret = handle_irc_packet(c,packet); break; case conn_class_w3route: ret = handle_w3route_packet(c,packet); break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] bad packet class %d (closing connection)",conn_get_socket(c),(int)packet_get_class(packet)); ret = -1; } packet_del_ref(packet); if (ret<0) { /* marking connection as "destroyed", memory will be freed later */ conn_set_state(c, conn_state_destroy); return -2; } } conn_set_in_size(c,0); } } return 0;}static int sd_tcpoutput(t_connection * c){ unsigned int currsize; unsigned int totsize; t_packet * packet; int csocket = conn_get_socket(c); totsize = 0; for (;;) { currsize = conn_get_out_size(c); if ((packet = conn_peek_outqueue(c)) == NULL) return -2; switch (net_send_packet(csocket,packet,&currsize)) /* avoid warning */ { case -1: /* marking connection as "destroyed", memory will be freed later */ conn_set_state(c, conn_state_destroy); return -2; case 0: /* still working on it */ conn_set_out_size(c,currsize); return 0; /* bail out */ case 1: /* done sending */ if (hexstrm) { fprintf(hexstrm,"%d: send class=%s[0x%02x] type=%s[0x%04x] length=%u\n", csocket, packet_get_class_str(packet),(unsigned int)packet_get_class(packet), packet_get_type_str(packet,packet_dir_from_server),packet_get_type(packet), packet_get_size(packet)); hexdump(hexstrm,packet_get_raw_data(packet,0),packet_get_size(packet)); } packet = conn_pull_outqueue(c); packet_del_ref(packet); conn_set_out_size(c,0); /* stop at about BNETD_MAX_OUTBURST (or until out of packets or EWOULDBLOCK) */ if (totsize>BNETD_MAX_OUTBURST || !conn_peek_outqueue(c)) return 0; totsize += currsize; break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -