static void write_cb(evutil_socket_t sock, short flags, void * args) { im_connection* conn = (im_connection*)args; if (evbuffer_get_length(conn->_out) > 0) evbuffer_write(conn->_out, conn->_fd); }
/* 服务器传信息过来了 this callback is invoked when there is data to read on bev. */ void sock_readcb(struct bufferevent *bev, void *ptr) { struct evbuffer *input = bufferevent_get_input(bev); evbuffer_write(input, STDOUT_FILENO); ++total_messages_read; total_bytes_read += evbuffer_get_length(input); }
void echo_write(int fd, short revents, void *conn) { struct conn * c = (struct conn *) conn; evbuffer_write(c->buf, fd); printf("fd %d: wrote echo\n", fd); echo_close(conn); }
static void bufferevent_writecb(int fd, short event, void *arg) { struct bufferevent *bufev = arg; int res = 0; short what = EVBUFFER_WRITE; if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } if (EVBUFFER_LENGTH(bufev->output)) { res = evbuffer_write(bufev->output, fd); if (res == -1) { #ifndef WIN32 /*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not *set errno. thus this error checking is not portable*/ if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) goto reschedule; /* error case */ what |= EVBUFFER_ERROR; #else goto reschedule; #endif } else if (res == 0) { /* eof case */ what |= EVBUFFER_EOF; } if (res <= 0) goto error; } if (EVBUFFER_LENGTH(bufev->output) != 0) bufferevent_add(&bufev->ev_write, bufev->timeout_write); /* * Invoke the user callback if our buffer is drained or below the * low watermark. */ if (bufev->writecb != NULL && EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) (*bufev->writecb)(bufev, bufev->cbarg); return; reschedule: if (EVBUFFER_LENGTH(bufev->output) != 0) bufferevent_add(&bufev->ev_write, bufev->timeout_write); return; error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }
static void client_writable(int fd, short event, void *arg) { int ret = evbuffer_write(out_buf, fd); if (ret < 0) { client_destroy(strerror(errno)); } else if (ret == 0) { client_destroy("null write?"); } else if (EVBUFFER_LENGTH(out_buf) > 0) { event_add(&wr_event, NULL); } }
static void bufferevent_writecb(int fd, short event, void *arg) { struct bufferevent *bufev = arg; int res = 0; short what = EVBUFFER_WRITE; if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } if (EVBUFFER_LENGTH(bufev->output)) { res = evbuffer_write(bufev->output, fd); if (res == -1) { #ifndef WIN32 if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) goto reschedule; what |= EVBUFFER_ERROR; #else goto reschedule; #endif } else if (res == 0) { what |= EVBUFFER_EOF; } if (res <= 0) goto error; } if (EVBUFFER_LENGTH(bufev->output) != 0) bufferevent_add(&bufev->ev_write, bufev->timeout_write); if (bufev->writecb != NULL && EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) (*bufev->writecb)(bufev, bufev->cbarg); return; reschedule: if (EVBUFFER_LENGTH(bufev->output) != 0) bufferevent_add(&bufev->ev_write, bufev->timeout_write); return; error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }
void end_session(struct session *s) { int err; logmsg(LOG_INFO, "#%d ending session", s->id); /* Flush output buffers. */ if (s->client_bufev && s->client_fd != -1) evbuffer_write(s->client_bufev->output, s->client_fd); if (s->server_bufev && s->server_fd != -1) evbuffer_write(s->server_bufev->output, s->server_fd); if (s->client_fd != -1) close(s->client_fd); if (s->server_fd != -1) close(s->server_fd); if (s->client_bufev) bufferevent_free(s->client_bufev); if (s->server_bufev) bufferevent_free(s->server_bufev); /* Remove rulesets by commiting empty ones. */ err = 0; if (prepare_commit(s->id) == -1) err = errno; else if (do_commit() == -1) { err = errno; do_rollback(); } if (err) logmsg(LOG_ERR, "#%d pf rule removal failed: %s", s->id, strerror(err)); LIST_REMOVE(s, entry); free(s); session_count--; }
static void bufferevent_writecb(int fd, short event, void *arg) { struct bufferevent *bufev = arg; int res = 0; short what = EVBUFFER_WRITE; if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } if (EVBUFFER_LENGTH(bufev->output)) { res = evbuffer_write(bufev->output, fd); if (res == -1) { if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) goto reschedule; /* error case */ what |= EVBUFFER_ERROR; } else if (res == 0) { /* eof case */ what |= EVBUFFER_EOF; } if (res <= 0) goto error; } if (EVBUFFER_LENGTH(bufev->output) != 0) bufferevent_add(&bufev->ev_write, bufev->timeout_write); /* * Invoke the user callback if our buffer is drained or below the * low watermark. */ if (bufev->writecb != NULL && EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) (*bufev->writecb)(bufev, bufev->cbarg); return; reschedule: if (EVBUFFER_LENGTH(bufev->output) != 0) bufferevent_add(&bufev->ev_write, bufev->timeout_write); return; error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }
int http_evbuffer_writeout(struct http_connection *hc, int can_skip) { int ret = 0; int origin_length = evbuffer_get_length(hc->evbout); int length = origin_length; int retry = 20; while((length = evbuffer_get_length(hc->evbout)) > 0 && retry--) { ret = evbuffer_write(hc->evbout, hc->fd); if (ret < 0) { if (errno == EAGAIN || errno == EINTR) { if (length == origin_length && can_skip) { dbprintf("connection %p evbuffer_write error %d," "stop write and drain buffer\n", hc, errno); evbuffer_drain(hc->evbout, -1); /* treat as a error occur if failed many times consecutively */ if (hc->consecutive_failed++ > 90) { dbprintf("connection %p have too many egain, stop it.\n", hc); return -1; } else { return 0; } } else { continue; } } else if (errno == ENOENT){ /* unknown error, but can be continue */ dbprintf("connection %p evbuffer_write error %d," "continue\n", hc, errno); continue; } else { printf("connection %p evbuffer_write error %d, " "stop write and end connection\n", hc, errno); return -1; } } } length = evbuffer_get_length(hc->evbout); if (length == 0) { hc->consecutive_failed = 0; } return origin_length - length; }
void write_chunk(uint64_t chunkid, struct evhttp_request *req) { DBG(); struct evbuffer *input; struct evbuffer *evb = evbuffer_new(); if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) { reply_error(req, HTTP_BADREQUEST, "should call write with POST"); return; } uint64_t start = 0, end; const char *range = evhttp_find_header(req->input_headers, "Range"); logging(LOG_DEUBG, "write Range Header: %s", range); if (range) { sscanf(range, "bytes=%" SCNu64 "-%" SCNu64, &start, &end); } input = req->input_buffer; hdd_chunk *chunk = hdd_create_chunk(chunkid, 0); //TODO int fd = open(chunk->path, O_WRONLY | O_CREAT, 0755); logging(LOG_DEUBG, "write seek to : %" PRIu64 "", start); logging(LOG_DEUBG, "evbuffer_get_length(input) = %d", evbuffer_get_length(input)); lseek(fd, start, SEEK_SET); if (-1 == fd) { reply_error(req, HTTP_INTERNAL, "could not open file : %s", chunk->path); return; } int rst = 0; while (evbuffer_get_length(input) && (rst = evbuffer_write(input, fd)) > 0) { ; } /*evbuffer_write(input, fd); */ close(fd); evbuffer_add(evb, "success", strlen("success")); evhttp_send_reply(req, HTTP_OK, "OK", evb); evbuffer_free(evb); }
int mhf_send_buffer(int fd, struct evbuffer *output_buffer) { int n; while(1) { #if 0 printf("send=%s\n",output_buffer->buffer); #endif n = evbuffer_write(output_buffer, fd); if (n == -1) { return -1; } else if (n == 0) { return -2; } if (EVBUFFER_LENGTH(output_buffer) == 0) { break; } } return 0; }
static void write_to_syslog(struct async_syslog_state* state) { while (state->write_ready && !state->buffers_empty) { struct evbuffer* buffer = state->buffers[state->buffer_get]; int r = evbuffer_write(buffer, state->fd); if (r < 0) { state->write_ready = 0; if (errno != EAGAIN && errno != EWOULDBLOCK) { close(state->fd); state->fd = -1; connect_to_syslog(state); } else { event_add(&state->event, NULL); } } else if (state->sock_type == SOCK_DGRAM || evbuffer_get_length(buffer) == 0) { if (evbuffer_get_length(buffer)) evbuffer_drain(buffer, evbuffer_get_length(buffer)); state->buffer_get += 1; state->buffer_get %= ASYNC_SYSLOG_BUFFER_SIZE; if (state->buffer_get == state->buffer_put) state->buffers_empty = 1; } } }
static void server_writable(int fd, short event, void *arg) { client_t *client = (client_t*)arg; #ifndef NO_CONSOLE_CLIENT // HACK um die Ausgabe des Consolenclients an // stdout statt stdin zu schicken. if (fd == STDIN_FILENO) fd = STDOUT_FILENO; #endif // Kompressionsrest flushen server_flush_compression(client); // Schreiben int ret = evbuffer_write(client->out_buf, fd); if (ret < 0) { server_destroy(client, strerror(errno)); } else if (ret == 0) { server_destroy(client, "null write?"); } else { if (EVBUFFER_LENGTH(client->out_buf) > 0) event_add(&client->wr_event, NULL); } }
int flush_db_log(const _Bool sync) { DBLog * const db_log = &app_context.db_log; if (db_log->db_log_fd == -1) { return 0; } struct evbuffer * const log_buffer = db_log->log_buffer; size_t to_write; to_write = evbuffer_get_length(log_buffer); if (to_write <= (size_t) 0U) { return 0; } if (sync == 0) { to_write = (size_t) 0U; } do { ssize_t written = evbuffer_write(log_buffer, db_log->db_log_fd); if (written < (ssize_t) to_write) { if (errno == EINTR) { continue; } if (errno == EAGAIN || errno == EWOULDBLOCK) { usleep((useconds_t) 1000000 / 10); continue; } return -1; } } while(0); if (sync != 0) { #ifdef HAVE_FDATASYNC fdatasync(db_log->db_log_fd); #else fsync(db_log->db_log_fd); #endif } return 0; }
void connection_client(int cfd, short event, void *arg) { struct client_state *cs = arg; int cmd, break_out = 0; int uid = 0, index = 0; // ignore clients that timeout if (event & EV_TIMEOUT) cs->state = FSM_EXIT; if (event & EV_READ) { if (cs->state != FSM_ENTER) { if (evbuffer_read(cs->evb, cfd, READ_BLOCK) <= 0) cs->state = FSM_EXIT; } else { if (evbuffer_read(cs->evb, cfd, 4) <= 0) cs->state = FSM_EXIT; } } while (!break_out) { switch (cs->state) { case FSM_ENTER: if (EVBUFFER_LENGTH(cs->evb) < sizeof(int)) { break_out = 1; break; } evbuffer_remove(cs->evb, &cmd, sizeof(cmd)); if (cmd == -1) cs->state = FSM_SYNC; else if (cmd == -2) { fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0) | O_NONBLOCK); cs->state = FSM_LOGIN; } else if (cmd >= 0) cs->state = FSM_EXIT; else { printf("unknown cmd=%d\n",cmd); cs->state = FSM_EXIT; } break; case FSM_SYNC: syncutmp(cfd); firstsync = 1; cs->state = FSM_EXIT; break; case FSM_LOGIN: if (firstsync) { if (EVBUFFER_LENGTH(cs->evb) < (2 + MAX_FRIEND + MAX_REJECT) * sizeof(int)) { break_out = 1; break; } evbuffer_remove(cs->evb, &index, sizeof(index)); evbuffer_remove(cs->evb, &uid, sizeof(uid)); if (index >= USHM_SIZE || index < 0) { fprintf(stderr, "bad index=%d\n", index); cs->state = FSM_EXIT; break; } if (uid > MAX_USERS || uid <= 0) { fprintf(stderr, "bad uid=%d\n", uid); cs->state = FSM_EXIT; break; } count_login++; processlogin(cs, uid, index); if (count_login >= 4000 || (time(NULL) - begin_time) > 30*60) showstat(); cs->state = FSM_WRITEBACK; break_out = 1; } else cs->state = FSM_EXIT; break; case FSM_WRITEBACK: if (event & EV_WRITE) if (evbuffer_write(cs->evb, cfd) <= 0 && EVBUFFER_LENGTH(cs->evb) > 0) break_out = 1; if (EVBUFFER_LENGTH(cs->evb) == 0) cs->state = FSM_EXIT; break; case FSM_EXIT: if (clients == MAX_CLIENTS) event_add(&ev, NULL); close(cfd); evbuffer_free(cs->evb); free(cs); clients--; return; break; } } if (cs->state == FSM_WRITEBACK) event_set(&cs->ev, cfd, EV_WRITE, (void *) connection_client, cs); event_add(&cs->ev, &tv); }
void shard_connection::handle_event(short evtype) { // connect() returning to us? normally we expect EV_WRITE, but for UNIX domain // sockets we workaround since connect() returned immediately, but we don't want // to do any I/O from the client::connect() call... if (!m_connected && (evtype == EV_WRITE || m_unix_sockaddr != NULL)) { int error = -1; socklen_t errsz = sizeof(error); if (getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, (void *) &error, &errsz) == -1) { benchmark_error_log("connect: error getting connect response (getsockopt): %s\n", strerror(errno)); return; } if (error != 0) { benchmark_error_log("connect: connection failed: %s\n", strerror(error)); return; } m_connected = true; if (!m_conns_manager->get_reqs_processed()) { process_first_request(); } else { benchmark_debug_log("reconnection complete, proceeding with test\n"); fill_pipeline(); } } assert(m_connected == true); if ((evtype & EV_WRITE) == EV_WRITE && evbuffer_get_length(m_write_buf) > 0) { if (evbuffer_write(m_write_buf, m_sockfd) < 0) { if (errno != EWOULDBLOCK) { benchmark_error_log("write error: %s\n", strerror(errno)); disconnect(); return; } } } if ((evtype & EV_READ) == EV_READ) { int ret = 1; while (ret > 0) { ret = evbuffer_read(m_read_buf, m_sockfd, -1); } if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { benchmark_error_log("read error: %s\n", strerror(errno)); disconnect(); return; } if (ret == 0) { benchmark_error_log("connection dropped.\n"); disconnect(); return; } if (evbuffer_get_length(m_read_buf) > 0) { process_response(); // process_response may have disconnected, in which case // we just abort and wait for libevent to call us back sometime if (!m_connected) { return; } } } // update event short new_evtype = 0; if (m_pending_resp) { new_evtype = EV_READ; } if (evbuffer_get_length(m_write_buf) > 0) { assert(!m_conns_manager->finished()); new_evtype |= EV_WRITE; } if (new_evtype) { int ret = event_assign(m_event, m_event_base, m_sockfd, new_evtype, cluster_client_event_handler, (void *)this); assert(ret == 0); ret = event_add(m_event, NULL); assert(ret == 0); } else if (m_conns_manager->finished()) { m_conns_manager->set_end_time(); } }
static void echo_read_cb(struct bufferevent *bev, void *ctx) { printf("echo_read_cb ctx:%p\n", ctx); /* This callback is invoked when there is data to read on bev. */ struct evbuffer *input = bufferevent_get_input(bev); /* Copy all the data from the input buffer to the output buffer. */ // evbuffer_add_buffer(output, input); // 能读到数据的时候 去连接其他server 而且是以阻塞的方式 printf("echo_read_cb1 \n"); struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); //servaddr.sin_family = AF_INET; ////servaddr.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ //if (inet_aton("192.168.1.104", &servaddr.sin_addr) == 0) //{ // perror("inet_aton failure!"); // printf("address:%u\n", servaddr.sin_addr.s_addr); // exit(EXIT_FAILURE); //} //servaddr.sin_port = htons(5188); /* Port 9876*/ // TODO 错误判断 char buff[64]; evutil_snprintf(buff, sizeof(buff), "%s:%d", "192.168.1.104", 5188); int servadd_len = sizeof(servaddr); //int retx = evutil_parse_sockaddr_port("192.168.1.104:5188", (struct sockaddr*)&servaddr, &servadd_len); int retx = evutil_parse_sockaddr_port(buff, (struct sockaddr*)&servaddr, &servadd_len); printf("address:%s\n", buff); if (retx < 0) { printf("address:error\n"); } else { printf("address:%u\n", servaddr.sin_addr.s_addr); } int sockconn; errno = 0; if ((sockconn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("socket failure"); exit(EXIT_FAILURE); } //evutil_make_socket_nonblocking(sockconn); struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(sockconn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(sockconn, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); // bufferevent_socket_new 只是分配内存 没有系统调用 struct bufferevent *bev1 = bufferevent_socket_new(ctx, sockconn, BEV_OPT_CLOSE_ON_FREE); //bufferevent_settimeout(bev1, 10, 10); //bev1 = bufferevent_socket_new(ctx, -1, BEV_OPT_CLOSE_ON_FREE); bufferevent_enable(bev1, EV_READ|EV_WRITE); bufferevent_setcb(bev1, NULL, NULL, eventcb, "hello"); //SetSocketBlockingEnabled(sockconn, 1); // 这里默认是阻塞的,会一直阻塞 直到连接成功 或超时 // // if (bufferevent_socket_connect(bev1, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { /* Error starting connection */ // 连接不能马上建立的时候 应该添加到写事件中 fprintf(stderr, "Connect failed.\n"); perror("connect..........."); //#define ETIMEDOUT 110 /* Connection timed out */ // 无条件超时 非自定义超时 走这里// //bufferevent_free(bev1); // 此时错误码是 BEV_EVENT_ERROR 在那里销毁 BEV_EVENT_ERROR //return -1; // 110错误码走到这里 11, 115错误码 不会走到这里 } printf("bufferevent_socket_connect return errno:%d \n", errno); ////#define EAGAIN 11 /* Try again */ ////#define ECONNREFUSED 111 /* Connection refused */ ////#define EINPROGRESS 115 /* Operation now in progress */ // connect 被超时打断11, // //if (errno != EAGAIN ) if (errno == EINPROGRESS) // 自定义 超时中断 { perror("self timeout............."); bufferevent_free(bev1); return; } else if (errno != 0) { perror("00buffevent_connect"); printf("bufferevent_socket_connect error\n"); //如果 在过程中 超时会被 打断 EINPROGRESS 115 /* Operation now in progress */ // 除了自定义超时timeout不宜在这里销毁 在 回调函数中销毁 不然调用不到回调函数// //bufferevent_free(bev1); return ; } else { // 连接成功 perror("11buffevent_connect"); printf("bufferevent_socket_connect success\n"); } //if (connect(sockconn, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) //{ // perror("connnect error"); // exit(EXIT_FAILURE); //} //else //{ // printf("connect success\n"); //} //char recvbuf[1024] = {0}; //memset(recvbuf, 0, sizeof(recvbuf)); //sleep(5); //read(sockconn, recvbuf, sizeof(recvbuf)); //printf("----%s-----\n", recvbuf); // struct evbuffer *input1 = bufferevent_get_input(bev1); // printf("before read ---------\n"); // bufferevent_read_buffer(bev1, input1); // size_t len = evbuffer_get_length(input1); // unsigned char * recvbuf = evbuffer_pullup(input1, len); // printf("end read len:%ld---------\n", len); // printf("----%s-----\n", recvbuf); //struct evbuffer * buffer = evbuffer_new(); struct evbuffer *buffer = bufferevent_get_input(bev1); struct evbuffer *buffero = bufferevent_get_output(bev1); evutil_socket_t fd = bufferevent_getfd(bev1); time_t rawtime; time ( &rawtime ); printf("before read ---------%ld\n", rawtime); int ret = evbuffer_read(buffer, fd, 1024); // not work // bufferevent_read_buffer(bev1, buffer); size_t len = evbuffer_get_length(buffer); time ( &rawtime ); printf("end readlen ---------%ld\n", len); unsigned char * recvbuf = evbuffer_pullup(buffer, len); printf("end read ---------%ld\n", rawtime); printf("----%s-----\n", recvbuf); evbuffer_drain(buffer, len); // int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd); time ( &rawtime ); printf("before write---------%ld\n", rawtime); sleep(10); time ( &rawtime ); printf("before write1---------%ld\n", rawtime); evbuffer_add(buffero, "hello,china", 12); ret = evbuffer_write(buffero, fd); // ret =write(fd, "hello,china", 12); if (ret < 0) { if (errno != 0) { perror("write "); } } time ( &rawtime ); printf("end write1 ---------%ld\n", rawtime); // 出现read 在connect 之前// //root@debian:~/programming/libevent/libevent2/libevent/sample/study-buffevent_block# ./echoserver_block // create listener success, base:0xfdbc40 // echo_read_cb ctx:0xfdbc40 // echo_read_cb1 // bufferevent_socket_connect return errno:11 // 11buffevent_connect: Resource temporarily unavailable // bufferevent_socket_connect success // ----hello,world----- // Connect okay,-------------------------- hello. // disConnect --------------------------. }
static evhtp_res recv_file_data (RecvFSM *fsm, gboolean *no_line) { char *line; size_t len; *no_line = FALSE; line = evbuffer_readln (fsm->line, &len, EVBUFFER_EOL_CRLF_STRICT); if (!line) { /* If we haven't read an entire line, but the line * buffer gets too long, flush the content to file. * It should be safe to assume the boundary line is * no longer than 10240 bytes. */ if (evbuffer_get_length (fsm->line) >= MAX_CONTENT_LINE) { seaf_debug ("[upload] recv file data %d bytes.\n", evbuffer_get_length(fsm->line)); if (fsm->recved_crlf) { if (writen (fsm->fd, "\r\n", 2) < 0) { seaf_warning ("[upload] Failed to write temp file: %s.\n", strerror(errno)); return EVHTP_RES_SERVERR; } } if (evbuffer_write (fsm->line, fsm->fd) < 0) { seaf_warning ("[upload] Failed to write temp file: %s.\n", strerror(errno)); return EVHTP_RES_SERVERR; } fsm->recved_crlf = FALSE; } *no_line = TRUE; } else if (strstr (line, fsm->boundary) != NULL) { seaf_debug ("[upload] file data ends.\n"); add_uploaded_file (fsm); g_free (fsm->input_name); fsm->input_name = NULL; fsm->state = RECV_HEADERS; free (line); } else { seaf_debug ("[upload] recv file data %d bytes.\n", len + 2); if (fsm->recved_crlf) { if (writen (fsm->fd, "\r\n", 2) < 0) { seaf_warning ("[upload] Failed to write temp file: %s.\n", strerror(errno)); return EVHTP_RES_SERVERR; } } if (writen (fsm->fd, line, len) < 0) { seaf_warning ("[upload] Failed to write temp file: %s.\n", strerror(errno)); free (line); return EVHTP_RES_SERVERR; } free (line); fsm->recved_crlf = TRUE; } return EVHTP_RES_OK; }
int client_send(client_t *client, const char *content) { evbuffer_add(client->output_buffer, content, strlen(content)); return evbuffer_write(client->output_buffer, client->fd); //return send(client->fd, content, strlen(content), 0); }
void server_destroy(client_t *client, const char *reason) { lua_pushliteral(L, "on_client_close"); lua_rawget(L, LUA_GLOBALSINDEX); lua_pushnumber(L, client_num(client)); lua_pushstring(L, reason); if (lua_pcall(L, 2, 0, 0) != 0) { fprintf(stderr, "error calling on_client_close: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); } // Quitmeldung senden if (client->is_gui_client) { packet_t packet; packet_init(&packet, PACKET_QUIT_MSG); packet_writeXX(&packet, reason, strlen(reason)); server_send_packet(&packet, client); } else { server_writeto(client, "connection terminated: ", 23); server_writeto(client, reason, strlen(reason)); server_writeto(client, "\r\n", 2); } // Kompressionsrest flushen server_flush_compression(client); // Rest rausschreiben (hier keine Fehlerbehandlung mehr, da eh egal). // Bei Filewritern muss nichts geschrieben werden, da deren Daten // immer direkt rausgeschrieben werden. if (!client->is_file_writer) evbuffer_write(client->out_buf, client->fd); evbuffer_free(client->in_buf); evbuffer_free(client->out_buf); free(client->kill_me); if (client->compress) deflateEnd(&client->strm); event_del(&client->rd_event); event_del(&client->wr_event); client->in_buf = NULL; client->out_buf = NULL; if (client->player) player_detach_client(client, client->player); assert(client->next == NULL); assert(client->prev == NULL); if (client->is_gui_client) { if (client->next_gui == client) { assert(client->prev_gui == client); guiclients = NULL; } else { client->next_gui->prev_gui = client->prev_gui; client->prev_gui->next_gui = client->next_gui; guiclients = client->next_gui; } } num_clients--; #ifndef NO_CONSOLE_CLIENT if (client->fd != STDIN_FILENO) #endif #ifdef WIN32 if (client->is_file_writer) { close(client->fd); } else { closesocket(client->fd); } #else close(client->fd); #endif }