static bool decide_startup_pool(PgSocket *client, PktHdr *pkt) { const char *username = NULL, *dbname = NULL; const char *key, *val; bool ok; while (1) { ok = mbuf_get_string(&pkt->data, &key); if (!ok || *key == 0) break; ok = mbuf_get_string(&pkt->data, &val); if (!ok) break; if (strcmp(key, "database") == 0) { slog_debug(client, "got var: %s=%s", key, val); dbname = val; } else if (strcmp(key, "user") == 0) { slog_debug(client, "got var: %s=%s", key, val); username = val; } else if (varcache_set(&client->vars, key, val)) { slog_debug(client, "got var: %s=%s", key, val); } else if (strlist_contains(cf_ignore_startup_params, key)) { slog_debug(client, "ignoring startup parameter: %s=%s", key, val); } else { slog_warning(client, "unsupported startup parameter: %s=%s", key, val); disconnect_client(client, true, "Unsupported startup parameter: %s", key); return false; } } if (!username || !username[0]) { disconnect_client(client, true, "No username supplied"); return false; } /* if missing dbname, default to username */ if (!dbname || !dbname[0]) dbname = username; /* check if limit allows, dont limit admin db nb: new incoming conn will be attached to PgSocket, thus get_active_client_count() counts it */ if (get_active_client_count() > cf_max_client_conn) { if (strcmp(dbname, "pgbouncer") != 0) { disconnect_client(client, true, "no more connections allowed (max_client_conn)"); return false; } } /* find pool and log about it */ if (set_pool(client, dbname, username)) { if (cf_log_connections) slog_info(client, "login attempt: db=%s user=%s", dbname, username); return true; } else { if (cf_log_connections) slog_info(client, "login failed: db=%s user=%s", dbname, username); return false; } }
bool set_pool(PgSocket *client, const char *dbname, const char *username, const char *password, bool takeover) { /* find database */ client->db = find_database(dbname); if (!client->db) { client->db = register_auto_database(dbname); if (!client->db) { disconnect_client(client, true, "No such database: %s", dbname); if (cf_log_connections) slog_info(client, "login failed: db=%s user=%s", dbname, username); return false; } else { slog_info(client, "registered new auto-database: db = %s", dbname ); } } /* are new connections allowed? */ if (client->db->db_disabled) { disconnect_client(client, true, "database does not allow connections: %s", dbname); return false; } if (client->db->admin) { if (admin_pre_login(client, username)) return finish_set_pool(client, takeover); } /* find user */ if (cf_auth_type == AUTH_ANY) { /* ignore requested user */ if (client->db->forced_user == NULL) { slog_error(client, "auth_type=any requires forced user"); disconnect_client(client, true, "bouncer config error"); return false; } client->auth_user = client->db->forced_user; } else { /* the user clients wants to log in as */ client->auth_user = find_user(username); if (!client->auth_user && client->db->auth_user) { if (takeover) { client->auth_user = add_db_user(client->db, username, password); return finish_set_pool(client, takeover); } start_auth_request(client, username); return false; } if (!client->auth_user) { disconnect_client(client, true, "No such user: %s", username); if (cf_log_connections) slog_info(client, "login failed: db=%s user=%s", dbname, username); return false; } } return finish_set_pool(client, takeover); }
bool set_pool(PgSocket *client, const char *dbname, const char *username) { PgDatabase *db; PgUser *user; /* find database */ db = find_database(dbname); if (!db) { db = register_auto_database(dbname); if (!db) { disconnect_client(client, true, "No such database: %s", dbname); return false; } else { slog_info(client, "registered new auto-database: db = %s", dbname ); } } /* are new connections allowed? */ if (db->db_disabled) { disconnect_client(client, true, "database does not allow connections: %s", dbname); return false; } /* find user */ if (cf_auth_type == AUTH_ANY) { /* ignore requested user */ user = NULL; if (db->forced_user == NULL) { slog_error(client, "auth_type=any requires forced user"); disconnect_client(client, true, "bouncer config error"); return false; } client->auth_user = db->forced_user; } else { /* the user clients wants to log in as */ user = find_user(username); if (!user) { disconnect_client(client, true, "No such user: %s", username); return false; } client->auth_user = user; } /* pool user may be forced */ if (db->forced_user) user = db->forced_user; client->pool = get_pool(db, user); if (!client->pool) { disconnect_client(client, true, "no memory for pool"); return false; } return check_fast_fail(client); }
void RedirectorSrv::server_sockevent( nlink_server *cptr, uint16 revents, void *myNet ) { NetworkInterface * client; struct nlink_client *ncptr; if(revents & PF_READ) { client = ( ( NetworkInterface * ) myNet )->getConnection( ); if (!client) return; uint32 nonblockingstate = true; IOCTL_SOCKET( client->getSocketID(), IOCTL_NOBLOCK, &nonblockingstate ); ncptr = new nlink_client; if(ncptr == NULL) return; memset(ncptr, 0, sizeof(*ncptr)); ncptr->hdr.type = RCLIENT; ncptr->hdr.fd = client->getSocketID(); nlink_insert((struct nlink *)ncptr); Client *pClient = new Client(); pClient->BindNI(client); ncptr->pClient = pClient; pClient->getNetwork()->sendData( mDestination.length( ), mDestination.c_str( ) ); Log::getSingleton( ).outString( "REDIRECTOR: Sent world server" ); disconnect_client( ncptr ); } }
static bool send_client_authreq(PgSocket *client) { uint8_t saltlen = 0; int res; int auth_type = client->client_auth_type; /* Always use plain text to communicate with clients during PAM authorization */ if (auth_type == AUTH_PAM) { auth_type = AUTH_PLAIN; } if (auth_type == AUTH_MD5) { saltlen = 4; get_random_bytes((void*)client->tmp_login_salt, saltlen); } else if (auth_type == AUTH_PLAIN) { /* nothing to do */ } else { return false; } SEND_generic(res, client, 'R', "ib", auth_type, client->tmp_login_salt, saltlen); if (!res) disconnect_client(client, false, "failed to send auth req"); return res; }
static void start_auth_request(PgSocket *client, const char *username) { int res; char quoted_username[64], query[128]; client->auth_user = client->db->auth_user; /* have to fetch user info from db */ client->pool = get_pool(client->db, client->db->auth_user); if (!find_server(client)) { client->wait_for_user_conn = true; return; } slog_noise(client, "Doing auth_conn query"); client->wait_for_user_conn = false; client->wait_for_user = true; if (!sbuf_pause(&client->sbuf)) { release_server(client->link); disconnect_client(client, true, "pause failed"); return; } client->link->ready = 0; pg_quote_literal(quoted_username, username, sizeof(quoted_username)); snprintf(query, sizeof(query), "SELECT usename, passwd FROM pg_shadow WHERE usename=%s", quoted_username); SEND_generic(res, client->link, 'Q', "s", query); if (!res) disconnect_server(client->link, false, "unable to send login query"); }
static void client_deref (struct ropa_client *c) { c->ref--; if (c->ref == 0) disconnect_client (c); }
void sigalrm_handler(int signum) { struct timeval t; gettimeofday(&t, NULL); for (int i = 0; i < MAX_CLIENTS; i++) { if (clients[i].sock != -1 && clients[i].sent == 0 && clients[i].last_msg_time.tv_sec + CONNECTION_TIMEOUT < t.tv_sec) { disconnect_client(i); printf("client deleted\n"); } } }
static bool login_as_unix_peer(PgSocket *client) { if (!pga_is_unix(&client->remote_addr)) goto fail; if (!check_unix_peer_name(sbuf_socket(&client->sbuf), client->auth_user->name)) goto fail; return finish_client_login(client); fail: disconnect_client(client, true, "unix socket login rejected"); return false; }
/* * Finishes the handshake after successful or unsuccessful authorization. * The function is only called from the main thread. */ static void pam_auth_finish(struct pam_auth_request *request) { PgSocket *client = request->client; bool authenticated = (request->status == PAM_STATUS_SUCCESS); if (authenticated) { safe_strcpy(client->auth_user->passwd, request->password, sizeof(client->auth_user->passwd)); sbuf_continue(&client->sbuf); } else { disconnect_client(client, true, "auth failed"); } }
void playerkick(int *cn) { server::clientinfo *ci = server::getinfo(*cn); if(!ci) { // todo: some error mechanism intret(RINT_ERROR); return; } disconnect_client(*cn, DISC_KICK); }
static bool login_via_cert(PgSocket *client) { struct tls *tls = client->sbuf.tls; if (!tls) { disconnect_client(client, true, "TLS connection required"); return false; } if (!tls_peer_cert_provided(client->sbuf.tls)) { disconnect_client(client, true, "TLS client certificate required"); return false; } log_debug("TLS cert login: %s", tls_peer_cert_subject(client->sbuf.tls)); if (!tls_peer_cert_contains_name(client->sbuf.tls, client->auth_user->name)) { disconnect_client(client, true, "TLS certificate name mismatch"); return false; } /* login successful */ return finish_client_login(client); }
int read_producer_stream(bionet_stream_t *stream) { stream_info_t *sinfo = bionet_stream_get_user_data(stream); alsa_t *alsa = sinfo->info.producer.alsa; int r; int frames, bytes; if (!check_alsa_poll(alsa)) { return 0; } r = pcm_read(alsa); if (r < 0) { // FIXME printf("read error on stream %s\n", bionet_stream_get_local_name(stream)); return 1; } frames = r; bytes = (frames * alsa->bytes_per_frame); hab_publish_stream(stream, alsa->audio_buffer, bytes); #if 0 FIXME r = write(client->socket, client->alsa->audio_buffer, bytes); if (r < 0) { printf("error writing stream %s to consumer: %s\n", bionet_stream_get_local_name(stream), strerror(errno)); disconnect_client(stream, client); return 1; } else if (r < bytes) { printf("short write to stream %s consumer", bionet_stream_get_local_name(stream)); disconnect_client(stream, client); return 1; } #endif return 0; }
static bool finish_set_pool(PgSocket *client, bool takeover) { PgUser *user = client->auth_user; /* pool user may be forced */ if (client->db->forced_user) { user = client->db->forced_user; } client->pool = get_pool(client->db, user); if (!client->pool) { disconnect_client(client, true, "no memory for pool"); return false; } if (cf_log_connections) slog_info(client, "login attempt: db=%s user=%s", client->db->name, client->auth_user->name); if (!check_fast_fail(client)) return false; if (takeover) return true; if (client->pool->db->admin) { if (!admin_post_login(client)) return false; } if (cf_auth_type <= AUTH_TRUST || client->own_user) { if (!finish_client_login(client)) return false; } else { if (!send_client_authreq(client)) { disconnect_client(client, false, "failed to send auth req"); return false; } } return true; }
static int sim_read_pkt(int fd, int client) { char buf[512]; Client *cl = clients + client, *dcl; int size, ret; if (client >= IBSIM_MAX_CLIENTS || !cl->pid) { IBWARN("pkt from unconnected client %d?!", client); return -1; } for (;;) { if ((size = read(fd, buf, sizeof(buf))) <= 0) return size; if ((size = process_packet(cl, buf, size, &dcl)) < 0) { IBWARN("process packet error - discarded"); continue; // not a network error } if (!dcl) continue; VERB("%s %d bytes (%zu) to client %d fd %d", dcl == cl ? "replying" : "forwarding", size, sizeof(struct sim_request), dcl->id, dcl->fd); // reply do { ret = write(dcl->fd, buf, size); } while ((errno == EAGAIN) && (ret == -1)); if (ret == size) return 0; if (ret < 0 && (errno == ECONNREFUSED || errno == ENOTCONN)) { IBWARN("client %u seems to be dead - disconnecting.", dcl->id); disconnect_client(dcl->id); } IBWARN("write failed: %m - pkt dropped"); if (dcl != cl) { /* reply timeout */ struct sim_request *r = (struct sim_request *)buf; r->status = htonl(110); ret = write(cl->fd, buf, size); } } return -1; // never reached }
int main(int argc, char *argv[]) { init_enet_server(PORT); LOG("Started server.\n"); struct moag moag; init_game(&moag); LOG("Initialized game.\n"); ENetEvent event; for (;;) { while (enet_host_service(get_server_host(), &event, 0)) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: LOG("Client connected.\n"); event.peer->data = (void *)client_connect(&moag); break; case ENET_EVENT_TYPE_DISCONNECT: LOG("Client disconnected.\n"); disconnect_client(&moag, (intptr_t)event.peer->data); break; case ENET_EVENT_TYPE_RECEIVE: on_receive(&moag, &event); enet_packet_destroy(event.packet); break; default: break; } } SDL_Delay(10); step_game(&moag); } uninit_enet(); LOG("Stopped server.\n"); return EXIT_SUCCESS; }
static int on_cread (void* userdata, int fd, size_t dummy) { (void) dummy; server* s = userdata; struct client *c = &p.client; unsigned x = c->samples_recvd % ARRAY_SIZE(c->wave); DPRINTF(2, "receiving samplebuf %u\n", x); if(sizeof(c->wave[0]) != recv(fd, c->wave[x], sizeof(c->wave[0]), 0)) { disconnect_client(s, fd); return 0; } pthread_mutex_lock(&c->mtx); c->samples_recvd++; pthread_mutex_unlock(&c->mtx); return 0; }
static int on_cconnect (void* userdata, struct sockaddr_storage* clientaddr, int fd) { (void) clientaddr; server* s = userdata; if(p.client.fd != -1) { disconnect_client(s, fd); return -1; } struct client* c = &p.client; c->fd = fd; c->terminate = 0; c->playback_handle = init_playback_device(s->audiodevice); pthread_mutex_init(&c->mtx, 0); pthread_create(&c->thr, 0, c_thread, c); return 0; }
static PyObject *playerKick(PyObject *self, PyObject *args) { int cn; server::clientinfo *ci; if(!PyArg_ParseTuple(args, "i", &cn)) return 0; ci = server::getinfo(cn); if(!ci) { PyErr_SetString(PyExc_ValueError, "Invalid cn specified"); return 0; } disconnect_client(cn, DISC_KICK); Py_INCREF(Py_None); return Py_None; }
static PyObject *playerDisconnect(PyObject *self, PyObject *args) { int cn; int reason; server::clientinfo *ci; if(!PyArg_ParseTuple(args, "ii", &cn, &reason)) return 0; ci = server::getinfo(cn); if(!ci) { PyErr_SetString(PyExc_ValueError, "Invalid cn specified"); return 0; } //enum { DISC_NONE = 0, DISC_EOP, DISC_CN, DISC_KICK, DISC_TAGT, DISC_IPBAN, DISC_PRIVATE, DISC_MAXCLIENTS, DISC_TIMEOUT, DISC_OVERFLOW, DISC_NUM }; if (reason < DISC_NONE || reason > DISC_NUM) { PyErr_SetString(PyExc_ValueError, "That is not a valid disconnect reason."); return 0; } disconnect_client(cn, reason); Py_INCREF(Py_None); return Py_None; }
static void start_auth_request(PgSocket *client, const char *username) { int res; PktBuf *buf; client->auth_user = client->db->auth_user; /* have to fetch user info from db */ client->pool = get_pool(client->db, client->db->auth_user); if (!find_server(client)) { client->wait_for_user_conn = true; return; } slog_noise(client, "Doing auth_conn query"); client->wait_for_user_conn = false; client->wait_for_user = true; if (!sbuf_pause(&client->sbuf)) { release_server(client->link); disconnect_client(client, true, "pause failed"); return; } client->link->ready = 0; res = 0; buf = pktbuf_dynamic(512); if (buf) { pktbuf_write_ExtQuery(buf, cf_auth_query, 1, username); res = pktbuf_send_immediate(buf, client->link); pktbuf_free(buf); /* * Should do instead: * res = pktbuf_send_queued(buf, client->link); * but that needs better integration with SBuf. */ } if (!res) disconnect_server(client->link, false, "unable to send login query"); }
static struct ropa_client * client_query (uint32_t host, uint16_t port) { struct ropa_client *c, *c_new; int ret; c = client_query_notalkback(host, port); if (c == NULL) { interfaceAddr remote; struct rx_connection *conn = NULL; c = obtain_client(); assert (c->state == ROPAC_FREE && c->li == NULL); c->state = ROPAC_LOOKUP_U; c->flags |= ROPAF_LOOKUP; client_init (c, host, port, NULL, NULL); conn = rx_NewConnection (host, port, CM_SERVICE_ID, rxnull_NewClientSecurityObject(), 0); if (conn == NULL) { free(c); return NULL; } retry: switch (c->state) { case ROPAC_DEAD: c->li = listaddtail (lru_clients, c); ret = ENETDOWN; break; case ROPAC_LOOKUP_U: ret = RXAFSCB_WhoAreYou (conn, &remote); if (ret == RXGEN_OPCODE) { c->state = ROPAC_LOOKUP; goto retry; } else if (ret == RX_CALL_DEAD) { c->state = ROPAC_DEAD; goto retry; } else { struct ropa_client ckey; ckey.uuid = remote.uuid; c_new = hashtabsearch (ht_clients_uuid, &ckey); if (c_new == NULL) { client_init (c, host, port, &remote.uuid, NULL); ret = RXAFSCB_InitCallBackState3(conn, &server_uuid); } else { client_update_interfaces (c_new, host, port, &remote); disconnect_client (c); c = c_new; listdel(lru_clients, c->li); c->li = NULL; } } break; case ROPAC_LOOKUP: { afsUUID uuid; ret = RXAFSCB_InitCallBackState(conn); if (ret == RX_CALL_DEAD) { c->state = ROPAC_DEAD; goto retry; } uuid_init_simple (&uuid, host); client_init (c, host, port, &uuid, NULL); break; } default: exit(-1); } rx_DestroyConnection (conn); if ((c->flags & ROPAF_WAITING) != 0) LWP_NoYieldSignal (c); c->flags &= ~(ROPAF_LOOKUP|ROPAF_WAITING); if (ret) { assert (c->li != NULL); return NULL; } assert (c->li == NULL); c->li = listaddhead (lru_clients, c); } else { /* c != NULL */ if ((c->flags & ROPAF_LOOKUP) != 0) { c->flags |= ROPAF_WAITING; LWP_WaitProcess (c); } assert (c->li != NULL); } return c; }
// server side processing of updates: does very little and most state is tracked // client only could be extended to move more gameplay to server (at expense of // lag) void process(ENetPacket * packet, int sender) { // sender may be -1 const u16 len = *(u16*) packet->data; if (ENET_NET_TO_HOST_16(len)!=packet->dataLength) { disconnect_client(sender, "packet length"); return; } u8 *end = packet->data+packet->dataLength; u8 *p = packet->data+2; char text[MAXTRANS]; int cn = -1, type; while (p<end) switch (type = getint(p)) { case SV_TEXT: sgetstr(); break; case SV_INITC2S: sgetstr(); strcpy_s(clients[cn].name, text); sgetstr(); getint(p); break; case SV_MAPCHANGE: { sgetstr(); int reqmode = getint(p); if (reqmode<0) reqmode = 0; if (smapname[0] && !mapreload && !vote(text, reqmode, sender)) return; mapreload = false; mode = reqmode; minremain = mode&1 ? 15 : 10; mapend = lastsec+minremain*60; interm = 0; strcpy_s(smapname, text); resetitems(); sender = -1; } break; case SV_ITEMLIST: { int n; while ((n = getint(p))!=-1) if (notgotitems) { server_entity se = { false, 0 }; while (sents.size()<=n) sents.push_back(se); sents[n].spawned = true; } notgotitems = false; } break; case SV_ITEMPICKUP: { const int n = getint(p); pickup(n, getint(p), sender); } break; case SV_PING: send2(false, cn, SV_PONG, getint(p)); break; case SV_POS: { cn = getint(p); if (cn<0 || cn>=clients.size() || clients[cn].type==ST_EMPTY) { disconnect_client(sender, "client num"); return; } int size = msgsizelookup(type); assert(size!=-1); loopi(size-2) getint(p); } break; case SV_SENDMAP: { sgetstr(); const auto mapsize = getint(p); sendmaps(sender, text, mapsize, p); } return; case SV_RECVMAP: send(sender, recvmap(sender)); return; case SV_EXT: // allows for new features that require no server updates for (int n = getint(p); n; n--) getint(p); break; default: { const int size = msgsizelookup(type); if (size==-1) { disconnect_client(sender, "tag type"); return; }; loopi(size-1) getint(p); } } if (p>end) { disconnect_client(sender, "end of packet"); return; }; multicast(packet, sender); }
int main (int argc, char *argv[]) { char cmd[10]; int num, end = 0; int cobex = FALSE, tcpobex = FALSE, btobex = FALSE, r320 = FALSE, usbobex = FALSE; obex_t *handle; #ifdef HAVE_BLUETOOTH bdaddr_t bdaddr; uint8_t channel = 0; #endif #ifdef HAVE_USB obex_interface_t *obex_intf; #endif struct context global_context = {0,}; #ifndef _WIN32 char *port; obex_ctrans_t custfunc; if( (argc == 2 || argc ==3) && (strcmp(argv[1], "-s") == 0 ) ) cobex = TRUE; if( (argc == 2 || argc ==3) && (strcmp(argv[1], "-r") == 0 ) ) { cobex = TRUE; r320 = TRUE; } #endif if( (argc == 2) && (strcmp(argv[1], "-i") == 0 ) ) tcpobex = TRUE; if( (argc >= 2) && (strcmp(argv[1], "-b") == 0 ) ) btobex = TRUE; if( (argc >= 2) && (strcmp(argv[1], "-u") == 0 ) ) usbobex = TRUE; if(cobex) { #ifndef _WIN32 if(argc == 3) port = argv[2]; else port = "/dev/ttyS0"; if(r320) printf("OBEX to R320 on %s!\n", port); else printf("OBEX on %s!\n", port); custfunc.customdata = cobex_open(port, r320); if(custfunc.customdata == NULL) { printf("cobex_open() failed\n"); return -1; } if(! (handle = OBEX_Init(OBEX_TRANS_CUSTOM, obex_event, 0))) { perror( "OBEX_Init failed"); return -1; } custfunc.connect = cobex_connect; custfunc.disconnect = cobex_disconnect; custfunc.write = cobex_write; custfunc.handleinput = cobex_handle_input; custfunc.listen = cobex_connect; // Listen and connect is 100% same on cable if(OBEX_RegisterCTransport(handle, &custfunc) < 0) { printf("Custom transport callback-registration failed\n"); } #else printf("Not implemented in Win32 yet.\n"); #endif // _WIN32 } else if(tcpobex) { printf("Using TCP transport\n"); if(! (handle = OBEX_Init(OBEX_TRANS_INET, obex_event, 0))) { perror( "OBEX_Init failed"); exit(0); } } else if(btobex) { #ifndef _WIN32 switch (argc) { #ifdef HAVE_BLUETOOTH case 4: str2ba(argv[2], &bdaddr); channel = atoi(argv[3]); break; case 3: str2ba(argv[2], &bdaddr); if (bacmp(&bdaddr, BDADDR_ANY) == 0) channel = atoi(argv[2]); else channel = BT_CHANNEL; break; case 2: bacpy(&bdaddr, BDADDR_ANY); channel = BT_CHANNEL; break; #endif default: printf("Wrong number of arguments\n"); exit(0); } printf("Using Bluetooth RFCOMM transport\n"); if(! (handle = OBEX_Init(OBEX_TRANS_BLUETOOTH, obex_event, 0))) { perror( "OBEX_Init failed"); exit(0); } #else printf("Not implemented in Win32 yet.\n"); #endif // _WIN32 } else if(usbobex) { #ifdef HAVE_USB int i, interfaces_number, intf_num; switch (argc) { case 2: printf("Using USB transport, querying available interfaces\n"); if(! (handle = OBEX_Init(OBEX_TRANS_USB, obex_event, 0))) { perror( "OBEX_Init failed"); exit(0); } interfaces_number = OBEX_FindInterfaces(handle, &obex_intf); for (i=0; i < interfaces_number; i++) printf("Interface %d: %s %s %s\n", i, obex_intf[i].usb.manufacturer, obex_intf[i].usb.product, obex_intf[i].usb.control_interface); printf("Use '%s -u interface_number' to run interactive OBEX test client\n", argv[0]); OBEX_Cleanup(handle); exit(0); break; case 3: intf_num = atoi(argv[2]); printf("Using USB transport \n"); if(! (handle = OBEX_Init(OBEX_TRANS_USB, obex_event, 0))) { perror( "OBEX_Init failed"); exit(0); } interfaces_number = OBEX_FindInterfaces(handle, &obex_intf); if (intf_num >= interfaces_number) { printf( "Invalid interface number\n"); exit(0); } obex_intf += intf_num; break; default: printf("Wrong number of arguments\n"); exit(0); } #else printf("Not compiled with USB support\n"); exit(0); #endif } else { printf("Using IrDA transport\n"); if(! (handle = OBEX_Init(OBEX_TRANS_IRDA, obex_event, 0))) { perror( "OBEX_Init failed"); exit(0); } } OBEX_SetUserData(handle, &global_context); printf( "OBEX Interactive test client/server.\n"); while (!end) { printf("> "); num = scanf("%s", cmd); switch (cmd[0] | 0x20) { case 'q': end=1; break; case 'g': get_client(handle, &global_context); break; case 't': setpath_client(handle); break; case 'p': put_client(handle); break; case 'x': push_client(handle); break; case 'c': /* First connect transport */ if(tcpobex) { if(TcpOBEX_TransportConnect(handle, NULL, 0) < 0) { printf("Transport connect error! (TCP)\n"); break; } } if(cobex) { if(OBEX_TransportConnect(handle, (void*) 1, 0) < 0) { printf("Transport connect error! (Serial)\n"); break; } } if(btobex) { #ifdef HAVE_BLUETOOTH if (bacmp(&bdaddr, BDADDR_ANY) == 0) { printf("Device address error! (Bluetooth)\n"); break; } if(BtOBEX_TransportConnect(handle, BDADDR_ANY, &bdaddr, channel) <0) { printf("Transport connect error! (Bluetooth)\n"); break; } #else printf("Transport not found! (Bluetooth)\n"); #endif } if (usbobex) { #ifdef HAVE_USB if (OBEX_InterfaceConnect(handle, obex_intf) < 0) { printf("Transport connect error! (USB)\n"); break; } #else printf("Transport not found! (USB)\n"); #endif } if (!tcpobex && !cobex && !btobex && !usbobex) { if(IrOBEX_TransportConnect(handle, IR_SERVICE) < 0) { printf("Transport connect error! (IrDA)\n"); break; } } // Now send OBEX-connect. connect_client(handle); break; case 'd': disconnect_client(handle); break; case 's': /* First register server */ if(tcpobex) { if(TcpOBEX_ServerRegister(handle, NULL, 0) < 0) { printf("Server register error! (TCP)\n"); break; } } if(cobex) { if(OBEX_ServerRegister(handle, (void*) 1, 0) < 0) { printf("Server register error! (Serial)\n"); break; } } if(btobex) { #ifdef HAVE_BLUETOOTH if(BtOBEX_ServerRegister(handle, BDADDR_ANY, channel) < 0) { printf("Server register error! (Bluetooth)\n"); break; } #else printf("Transport not found! (Bluetooth)\n"); #endif } if (usbobex) { printf("Transport not found! (USB)\n"); } if (!tcpobex && !cobex && !btobex && !usbobex) { if(IrOBEX_ServerRegister(handle, IR_SERVICE) < 0) { printf("Server register error! (IrDA)\n"); break; } } /* No process server events */ server_do(handle); break; default: printf("Unknown command %s\n", cmd); } } #ifndef _WIN32 if(cobex) cobex_close(custfunc.customdata); #endif return 0; }
int main(int argc, char *argv[]) { int port; char *args_help = "Enter port and path to unix socket.\n"; if (read_args(argc, argv, &port, &socket_unix_path) != 0) { printf(args_help); return 1; } atexit(cleanup); struct sigaction act; memset(&act, 0, sizeof act); act.sa_handler = sigint_handler; sigaction(SIGINT, &act, NULL); sigaction(SIGTSTP, &act, NULL); act.sa_handler = sigalrm_handler; sigaction(SIGALRM, &act, NULL); for (int i = 0; i < MAX_CLIENTS; i++) { clients[i].sock = -1; clients[i].username[0] = '\0'; clients[i].sent = 0; } unlink(socket_unix_path); unix_socket = prepare_unix_socket(socket_unix_path); internet_socket = prepare_internet_socket(port); if (unix_socket == -1 || internet_socket == -1) { printf("Error while creating sockets occurred.\n"); return 1; } struct itimerval timer_val; struct timeval timer_time; timer_time.tv_sec = 3; timer_time.tv_usec = 0; timer_val.it_interval = timer_time; timer_val.it_value = timer_time; setitimer(ITIMER_REAL, &timer_val, NULL); fd_set read_sock_set; FD_ZERO(&sock_set); int fd_max = unix_socket > internet_socket ? unix_socket : internet_socket; FD_SET(unix_socket, &sock_set); FD_SET(internet_socket, &sock_set); struct timeval msg_time; while(1) { gettimeofday(&msg_time, NULL); read_sock_set = sock_set; if (select(fd_max + 1, &read_sock_set, NULL , NULL , NULL) < 0) { if (errno == EINTR) continue; else { printf("Error while executing select occurred.\n"); sleep(1); continue; } } int client_unix_sock = -1; int client_internet_sock = -1; if (clients_connected < MAX_CLIENTS) { if (FD_ISSET(unix_socket, &read_sock_set)) { if ((client_unix_sock = accept(unix_socket, NULL, NULL)) == -1) printf("Cannot accept new client connection!\n"); } if (FD_ISSET(internet_socket, &read_sock_set) && !(clients_connected + 1 == MAX_CLIENTS && client_unix_sock != -1)) if ((client_internet_sock = accept(internet_socket, NULL, NULL)) == -1) printf("Cannot accept new client connection!\n"); for (int i = 0; i < MAX_CLIENTS && (client_unix_sock != -1 || client_internet_sock != -1); i++) { if (clients[i].sock == -1) { int client_sock; if (client_unix_sock != -1) { client_sock = client_unix_sock; client_unix_sock = -1; } else { client_sock = client_internet_sock; client_internet_sock = -1; } FD_SET(client_sock, &sock_set); if (client_sock > fd_max) { fd_max = client_sock; } clients[i].sock = client_sock; clients[i].last_msg_time = msg_time; clients_connected++; printf("client accepted\n"); } } } else { if (FD_ISSET(unix_socket, &read_sock_set)) { client_unix_sock = accept(unix_socket, NULL, NULL); close(client_unix_sock); } if (FD_ISSET(internet_socket, &read_sock_set)) { client_internet_sock = accept(internet_socket, NULL, NULL); close(client_internet_sock); } } for (int i = 0; i < MAX_CLIENTS; i++) { if (clients[i].sock == -1 || !FD_ISSET(clients[i].sock, &read_sock_set)) { continue; } struct Message msg; clients[i].sent = 1; if(recv(clients[i].sock, &msg, sizeof(msg), 0) <= 0) { printf("%s disconnected\n", clients[i].username); strcpy(msg.username, clients[i].username); strcpy(msg.message, "Disconnected\n"); broadcast(msg, clients[i].sock); disconnect_client(i); continue; } clients[i].last_msg_time = msg_time; printf("%s", msg.message); strcpy(clients[i].username, msg.username); broadcast(msg, clients[i].sock); } } }
bool handle_auth_response(PgSocket *client, PktHdr *pkt) { uint16_t columns; uint32_t length; const char *username, *password; PgUser user; PgSocket *server = client->link; switch(pkt->type) { case 'T': /* RowDescription */ if (!mbuf_get_uint16be(&pkt->data, &columns)) { disconnect_server(server, false, "bad packet"); return false; } if (columns != 2u) { disconnect_server(server, false, "expected 1 column from login query, not %hu", columns); return false; } break; case 'D': /* DataRow */ memset(&user, 0, sizeof(user)); if (!mbuf_get_uint16be(&pkt->data, &columns)) { disconnect_server(server, false, "bad packet"); return false; } if (columns != 2u) { disconnect_server(server, false, "expected 1 column from login query, not %hu", columns); return false; } if (!mbuf_get_uint32be(&pkt->data, &length)) { disconnect_server(server, false, "bad packet"); return false; } if (!mbuf_get_chars(&pkt->data, length, &username)) { disconnect_server(server, false, "bad packet"); return false; } if (sizeof(user.name) - 1 < length) length = sizeof(user.name) - 1; memcpy(user.name, username, length); if (!mbuf_get_uint32be(&pkt->data, &length)) { disconnect_server(server, false, "bad packet"); return false; } if (length == (uint32_t)-1) { // NULL - set an md5 password with an impossible value, // so that nothing will ever match password = "******"; length = 3; } else { if (!mbuf_get_chars(&pkt->data, length, &password)) { disconnect_server(server, false, "bad packet"); return false; } } if (sizeof(user.passwd) - 1 < length) length = sizeof(user.passwd) - 1; memcpy(user.passwd, password, length); client->auth_user = add_db_user(client->db, user.name, user.passwd); if (!client->auth_user) { disconnect_server(server, false, "unable to allocate new user for auth"); return false; } break; case 'C': /* CommandComplete */ break; case 'Z': /* ReadyForQuery */ sbuf_prepare_skip(&client->link->sbuf, pkt->len); if (!client->auth_user) { if (cf_log_connections) slog_info(client, "login failed: db=%s", client->db->name); disconnect_client(client, true, "No such user"); } else { slog_noise(client, "auth query complete"); client->link->resetting = true; sbuf_continue(&client->sbuf); } // either sbuf_continue or disconnect_client could disconnect the server // way down in their bowels of other callbacks. so check that, and // return appropriately (similar to reuse_on_release) if (server->state == SV_FREE || server->state == SV_JUSTFREE) return false; return true; default: disconnect_server(server, false, "unexpected response from login query"); return false; } sbuf_prepare_skip(&server->sbuf, pkt->len); return true; }
void kiro_server_realloc (KiroServer *self, void *mem, size_t size) { if (!self) return; g_debug ("Starting realloc"); struct kiro_rdma_mem rdma_mem; rdma_mem.mem = mem; rdma_mem.size = size; KiroServerPrivate *priv = KIRO_SERVER_GET_PRIVATE (self); G_LOCK (connection_handling); G_LOCK (rdma_handling); priv->mem = mem; priv->mem_size = size; if (!priv->clients) { g_debug ("No clients to reconnect. Done."); G_UNLOCK (rdma_handling); G_UNLOCK (connection_handling); return; } g_list_foreach (priv->clients, request_client_realloc, &rdma_mem); // Swap the two lists. See Note above. GList *tmp = priv->clients; priv->clients = realloc_list; realloc_list = tmp; G_UNLOCK (rdma_handling); guint timeout = g_timeout_add_seconds (2, client_realloc_timeout, NULL); timeout_done = FALSE; while (!timeout_done) { if (!realloc_list) { g_debug ("All clients have ACKed"); break; // all clients ACKed } } GSource *timeout_source = g_main_context_find_source_by_id (NULL, timeout); if (timeout_source) { g_source_destroy (timeout_source); } G_LOCK (realloc_timeout); GList *current = g_list_first (realloc_list); while (current) { struct kiro_client_connection *cc = (struct kiro_client_connection *)current->data; g_debug ("Client %i did not ACK the REALLOC request in time.", cc->id); GList *client = g_list_find (priv->clients, current->data); if (client) { priv->clients = g_list_delete_link (priv->clients, client); } disconnect_client (current->data, NULL); current = g_list_next (current); } if (realloc_list) { g_list_free (realloc_list); realloc_list = NULL; } G_UNLOCK (realloc_timeout); g_debug ("Realloc procedure done!"); G_UNLOCK (connection_handling); }
/* decide on packets of client in login phase */ static bool handle_client_startup(PgSocket *client, PktHdr *pkt) { const char *passwd; const uint8_t *key; bool ok; SBuf *sbuf = &client->sbuf; /* don't tolerate partial packets */ if (incomplete_pkt(pkt)) { disconnect_client(client, true, "client sent partial pkt in startup phase"); return false; } if (client->wait_for_welcome) { if (finish_client_login(client)) { /* the packet was already parsed */ sbuf_prepare_skip(sbuf, pkt->len); return true; } else return false; } switch (pkt->type) { case PKT_SSLREQ: slog_noise(client, "C: req SSL"); slog_noise(client, "P: nak"); /* reject SSL attempt */ if (!sbuf_answer(&client->sbuf, "N", 1)) { disconnect_client(client, false, "failed to nak SSL"); return false; } break; case PKT_STARTUP_V2: disconnect_client(client, true, "Old V2 protocol not supported"); return false; case PKT_STARTUP: if (client->pool) { disconnect_client(client, true, "client re-sent startup pkt"); return false; } if (!decide_startup_pool(client, pkt)) return false; if (client->pool->db->admin) { if (!admin_pre_login(client)) return false; } if (cf_auth_type <= AUTH_TRUST || client->own_user) { if (!finish_client_login(client)) return false; } else { if (!send_client_authreq(client)) { disconnect_client(client, false, "failed to send auth req"); return false; } } break; case 'p': /* PasswordMessage */ /* haven't requested it */ if (cf_auth_type <= AUTH_TRUST) { disconnect_client(client, true, "unrequested passwd pkt"); return false; } ok = mbuf_get_string(&pkt->data, &passwd); if (ok && check_client_passwd(client, passwd)) { if (!finish_client_login(client)) return false; } else { disconnect_client(client, true, "Auth failed"); return false; } break; case PKT_CANCEL: if (mbuf_avail_for_read(&pkt->data) == BACKENDKEY_LEN && mbuf_get_bytes(&pkt->data, BACKENDKEY_LEN, &key)) { memcpy(client->cancel_key, key, BACKENDKEY_LEN); accept_cancel_request(client); } else disconnect_client(client, false, "bad cancel request"); return false; default: disconnect_client(client, false, "bad packet"); return false; } sbuf_prepare_skip(sbuf, pkt->len); client->request_time = get_cached_time(); return true; }
/* callback from SBuf */ bool client_proto(SBuf *sbuf, SBufEvent evtype, struct MBuf *data) { bool res = false; PgSocket *client = container_of(sbuf, PgSocket, sbuf); PktHdr pkt; Assert(!is_server_socket(client)); Assert(client->sbuf.sock); Assert(client->state != CL_FREE); /* may happen if close failed */ if (client->state == CL_JUSTFREE) return false; switch (evtype) { case SBUF_EV_CONNECT_OK: case SBUF_EV_CONNECT_FAILED: /* ^ those should not happen */ case SBUF_EV_RECV_FAILED: disconnect_client(client, false, "client unexpected eof"); break; case SBUF_EV_SEND_FAILED: disconnect_server(client->link, false, "Server connection closed"); break; case SBUF_EV_READ: if (mbuf_avail_for_read(data) < NEW_HEADER_LEN && client->state != CL_LOGIN) { slog_noise(client, "C: got partial header, trying to wait a bit"); return false; } if (!get_header(data, &pkt)) { char hex[8*2 + 1]; disconnect_client(client, true, "bad packet header: '%s'", hdr2hex(data, hex, sizeof(hex))); return false; } slog_noise(client, "pkt='%c' len=%d", pkt_desc(&pkt), pkt.len); client->request_time = get_cached_time(); switch (client->state) { case CL_LOGIN: res = handle_client_startup(client, &pkt); break; case CL_ACTIVE: if (client->wait_for_welcome) res = handle_client_startup(client, &pkt); else res = handle_client_work(client, &pkt); break; case CL_WAITING: fatal("why waiting client in client_proto()"); default: fatal("bad client state: %d", client->state); } break; case SBUF_EV_FLUSH: /* client is not interested in it */ break; case SBUF_EV_PKT_CALLBACK: /* unused ATM */ break; } return res; }
/* decide on packets of logged-in client */ static bool handle_client_work(PgSocket *client, PktHdr *pkt) { SBuf *sbuf = &client->sbuf; switch (pkt->type) { /* one-packet queries */ case 'Q': /* Query */ if (cf_disable_pqexec) { slog_error(client, "Client used 'Q' packet type."); disconnect_client(client, true, "PQexec disallowed"); return false; } case 'F': /* FunctionCall */ /* request immediate response from server */ case 'H': /* Flush */ case 'S': /* Sync */ /* copy end markers */ case 'c': /* CopyDone(F/B) */ case 'f': /* CopyFail(F/B) */ /* * extended protocol allows server (and thus pooler) * to buffer packets until sync or flush is sent by client */ case 'P': /* Parse */ case 'E': /* Execute */ case 'C': /* Close */ case 'B': /* Bind */ case 'D': /* Describe */ case 'd': /* CopyData(F/B) */ /* update stats */ if (!client->query_start) { client->pool->stats.request_count++; client->query_start = get_cached_time(); } if (client->pool->db->admin) return admin_handle_client(client, pkt); /* aquire server */ if (!find_server(client)) return false; client->pool->stats.client_bytes += pkt->len; /* tag the server as dirty */ client->link->ready = false; client->link->idle_tx = false; /* forward the packet */ sbuf_prepare_send(sbuf, &client->link->sbuf, pkt->len); break; /* client wants to go away */ default: slog_error(client, "unknown pkt from client: %d/0x%x", pkt->type, pkt->type); disconnect_client(client, true, "unknown pkt"); return false; case 'X': /* Terminate */ disconnect_client(client, false, "client close request"); return false; } return true; }