static int ois_read_into_buffer(SMSCenter *smsc, long wait_usec) { int ret; SAY(8, "ois_read_into_buffer"); if (smsc->socket == -1) { if ((smsc->ois_flags & OIS_FLAG_CLOSED) == 0) { debug("bb.sms.ois", 0, "attempting to read from a closed socket"); smsc->ois_flags |= OIS_FLAG_CLOSED; } return 0; } else { smsc->ois_flags &= ~OIS_FLAG_CLOSED; } ret = read_available(smsc->socket, wait_usec); if (ret > 0) { time(&smsc->ois_alive); ret = smscenter_read_into_buffer(smsc); if (ret > 0 || (ret == 0 && smsc->buflen > 0)) { SAY(2, "ois_read_into_buffer got something"); } else if (ret == 0) { if (smsc->buflen > 0) { SAY(2, "ois_read_into_buffer has something"); ret = 1; } SAY(4, "ois_read_into_buffer: ois_disconnect"); ois_disconnect(smsc); } } return ret; }
size_t pop (T * output_buffer, size_t output_count, T * internal_buffer, size_t max_size) { const size_t write_index = write_index_.load(memory_order_acquire); const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread const size_t avail = read_available(write_index, read_index, max_size); if (avail == 0) return 0; output_count = (std::min)(output_count, avail); size_t new_read_index = read_index + output_count; if (read_index + output_count > max_size) { /* copy data in two sections */ const size_t count0 = max_size - read_index; const size_t count1 = output_count - count0; copy_and_delete(internal_buffer + read_index, internal_buffer + max_size, output_buffer); copy_and_delete(internal_buffer, internal_buffer + count1, output_buffer + count0); new_read_index -= max_size; } else { copy_and_delete(internal_buffer + read_index, internal_buffer + read_index + output_count, output_buffer); if (new_read_index == max_size) new_read_index = 0; } read_index_.store(new_read_index, memory_order_release); return output_count; }
size_t pop_to_output_iterator (OutputIterator it, T * internal_buffer, size_t max_size) { const size_t write_index = write_index_.load(memory_order_acquire); const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread const size_t avail = read_available(write_index, read_index, max_size); if (avail == 0) return 0; size_t new_read_index = read_index + avail; if (read_index + avail > max_size) { /* copy data in two sections */ const size_t count0 = max_size - read_index; const size_t count1 = avail - count0; it = copy_and_delete(internal_buffer + read_index, internal_buffer + max_size, it); copy_and_delete(internal_buffer, internal_buffer + count1, it); new_read_index -= max_size; } else { copy_and_delete(internal_buffer + read_index, internal_buffer + read_index + avail, it); if (new_read_index == max_size) new_read_index = 0; } read_index_.store(new_read_index, memory_order_release); return avail; }
size_t consume_all (Functor & functor, T * internal_buffer, size_t max_size) { const size_t write_index = write_index_.load(memory_order_acquire); const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread const size_t avail = read_available(write_index, read_index, max_size); if (avail == 0) return 0; const size_t output_count = avail; size_t new_read_index = read_index + output_count; if (read_index + output_count > max_size) { /* copy data in two sections */ const size_t count0 = max_size - read_index; const size_t count1 = output_count - count0; run_functor_and_delete(internal_buffer + read_index, internal_buffer + max_size, functor); run_functor_and_delete(internal_buffer, internal_buffer + count1, functor); new_read_index -= max_size; } else { run_functor_and_delete(internal_buffer + read_index, internal_buffer + read_index + output_count, functor); if (new_read_index == max_size) new_read_index = 0; } read_index_.store(new_read_index, memory_order_release); return output_count; }
unsigned read(void* buf, unsigned len) { auto allowed = std::min(len, read_available()); memcpy(buf, read_begin(), allowed); mNumRead += allowed; return allowed; }
// read (and discard) all available data. void read_flush(int fd) { int avail; char buf[1024]; do { avail=read_available(fd); if (avail>1024) avail=1024; read(fd, buf, avail); } while (avail>0); }
// read (and discard) all available data. void read_flush(int fd) { int avail; char buf[1024]; do { avail=read_available(fd); if (avail>1024) avail=1024; int res = read(fd, buf, avail); res++; // trick to ignore compiler warnings about unread result } while (avail>0); }
static void udp_receiver(void *arg) { Octstr *datagram, *cliaddr; int ret; Msg *msg; Udpc *conn = arg; Octstr *ip; gwlist_add_producer(incoming_wdp); gwlist_add_producer(flow_threads); gwthread_wakeup(MAIN_THREAD_ID); /* remove messages from socket until it is closed */ while (bb_status != BB_DEAD && bb_status != BB_SHUTDOWN) { gwlist_consume(isolated); /* block here if suspended/isolated */ if (read_available(conn->fd, 100000) < 1) continue; ret = udp_recvfrom(conn->fd, &datagram, &cliaddr); if (ret == -1) { if (errno == EAGAIN) /* No datagram available, don't block. */ continue; error(errno, "Failed to receive an UDP"); /* * just continue, or is there ANY error that would result * in situation where it would be better to break; or even * die off? - Kalle 28.2 */ continue; } /* discard the message if the client is not allowed */ ip = udp_get_ip(cliaddr); if (!is_allowed_ip(allow_ip, deny_ip, ip)) { warning(0, "UDP: Discarding packet from %s, IP is denied.", octstr_get_cstr(ip)); octstr_destroy(datagram); } else { debug("bb.udp", 0, "datagram received"); msg = msg_create(wdp_datagram); msg->wdp_datagram.source_address = udp_get_ip(cliaddr); msg->wdp_datagram.source_port = udp_get_port(cliaddr); msg->wdp_datagram.destination_address = udp_get_ip(conn->addr); msg->wdp_datagram.destination_port = udp_get_port(conn->addr); msg->wdp_datagram.user_data = datagram; gwlist_produce(incoming_wdp, msg); counter_increase(incoming_wdp_counter); } octstr_destroy(cliaddr); octstr_destroy(ip); } gwlist_remove_producer(incoming_wdp); gwlist_remove_producer(flow_threads); }
static void proxy_thread(void *arg) { int ss, cs; /* server and client sockets */ int fl; /* socket flags */ Octstr *addr = NULL; int forward; Octstr *tmp; run_thread = 1; ss = cs = -1; /* create client binding, only if we have a remote server * and make the client socet non-blocking */ if (remote_host != NULL) { cs = udp_client_socket(); fl = fcntl(cs, F_GETFL); fcntl(cs, F_SETFL, fl | O_NONBLOCK); addr = udp_create_address(remote_host, remote_port); } /* create server binding */ ss = udp_bind(our_port, octstr_get_cstr(our_host)); /* make the server socket non-blocking */ fl = fcntl(ss, F_GETFL); fcntl(ss, F_SETFL, fl | O_NONBLOCK); if (ss == -1) panic(0, "RADIUS: Couldn't set up server socket for port %ld.", our_port); while (run_thread) { RADIUS_PDU *pdu, *r; Octstr *data, *rdata; Octstr *from_nas, *from_radius; pdu = r = NULL; data = rdata = from_nas = from_radius = NULL; if (read_available(ss, 100000) < 1) continue; /* get request from NAS */ if (udp_recvfrom(ss, &data, &from_nas) == -1) { if (errno == EAGAIN) /* No datagram available, don't block. */ continue; error(0, "RADIUS: Couldn't receive request data from NAS"); continue; } tmp = udp_get_ip(from_nas); info(0, "RADIUS: Got data from NAS <%s:%d>", octstr_get_cstr(tmp), udp_get_port(from_nas)); octstr_destroy(tmp); octstr_dump(data, 0); /* unpacking the RADIUS PDU */ if ((pdu = radius_pdu_unpack(data)) == NULL) { warning(0, "RADIUS: Couldn't unpack PDU from NAS, ignoring."); goto error; } info(0, "RADIUS: from NAS: PDU type: %s", pdu->type_name); /* authenticate the Accounting-Request packet */ if (radius_authenticate_pdu(pdu, &data, secret_nas) == 0) { warning(0, "RADIUS: Authentication failed for PDU from NAS, ignoring."); goto error; } /* store to hash table if not present yet */ mutex_lock(radius_mutex); forward = update_tables(pdu); mutex_unlock(radius_mutex); /* create response PDU for NAS */ r = radius_pdu_create(0x05, pdu); /* * create response authenticator * code+identifier(req)+length+authenticator(req)+(attributes)+secret */ r->u.Accounting_Response.identifier = pdu->u.Accounting_Request.identifier; r->u.Accounting_Response.authenticator = octstr_duplicate(pdu->u.Accounting_Request.authenticator); /* pack response for NAS */ rdata = radius_pdu_pack(r); /* creates response autenticator in encoded PDU */ radius_authenticate_pdu(r, &rdata, secret_nas); /* * forward request to remote RADIUS server only if updated * and if we have a configured remote RADIUS server */ if ((remote_host != NULL) && forward) { if (udp_sendto(cs, data, addr) == -1) { error(0, "RADIUS: Couldn't send to remote RADIUS <%s:%ld>.", octstr_get_cstr(remote_host), remote_port); } else if (read_available(cs, remote_timeout) < 1) { error(0, "RADIUS: Timeout for response from remote RADIUS <%s:%ld>.", octstr_get_cstr(remote_host), remote_port); } else if (udp_recvfrom(cs, &data, &from_radius) == -1) { error(0, "RADIUS: Couldn't receive from remote RADIUS <%s:%ld>.", octstr_get_cstr(remote_host), remote_port); } else { info(0, "RADIUS: Got data from remote RADIUS <%s:%d>.", octstr_get_cstr(udp_get_ip(from_radius)), udp_get_port(from_radius)); octstr_dump(data, 0); /* XXX unpack the response PDU and check if the response * authenticator is valid */ } } /* send response to NAS */ if (udp_sendto(ss, rdata, from_nas) == -1) error(0, "RADIUS: Couldn't send response data to NAS <%s:%d>.", octstr_get_cstr(udp_get_ip(from_nas)), udp_get_port(from_nas)); error: radius_pdu_destroy(pdu); radius_pdu_destroy(r); octstr_destroy(rdata); octstr_destroy(data); octstr_destroy(from_nas); debug("radius.proxy", 0, "RADIUS: Mapping table contains %ld elements", dict_key_count(radius_table)); debug("radius.proxy", 0, "RADIUS: Session table contains %ld elements", dict_key_count(session_table)); debug("radius.proxy", 0, "RADIUS: Client table contains %ld elements", dict_key_count(client_table)); } octstr_destroy(addr); }
size_t read_available(size_t max_size) const { size_t write_index = write_index_.load(memory_order_acquire); const size_t read_index = read_index_.load(memory_order_relaxed); return read_available(write_index, read_index, max_size); }
static void udp_receiver(void *arg) { Octstr *datagram, *cliaddr; int ret; Msg *msg; Udpc *conn = arg; Octstr *ip; gwlist_add_producer(incoming_wdp); gwlist_add_producer(flow_threads); gwthread_wakeup(MAIN_THREAD_ID); /* remove messages from socket until it is closed */ while (1) { if (read_available(conn->fd, 100000) < 1) continue; ret = udp_recvfrom(conn->fd, &datagram, &cliaddr); if (ret == -1) { if (errno == EAGAIN) /* No datagram available, don't block. */ continue; error(errno, "Failed to receive an UDP"); continue; } ip = udp_get_ip(cliaddr); msg = msg_create(wdp_datagram); msg->wdp_datagram.source_address = udp_get_ip(cliaddr); msg->wdp_datagram.source_port = udp_get_port(cliaddr); msg->wdp_datagram.destination_address = udp_get_ip(conn->addr); msg->wdp_datagram.destination_port = udp_get_port(conn->addr); msg->wdp_datagram.user_data = datagram; info(0, "datagram received <%s:%d> -> <%s:%d>", octstr_get_cstr(udp_get_ip(cliaddr)), udp_get_port(cliaddr), octstr_get_cstr(udp_get_ip(conn->addr)), udp_get_port(conn->addr)); dump(msg); /* * Descide if this is (a) or (b) UDP packet and add them to the * corresponding queues */ if (octstr_compare(conn->addr, conn->map_addr) == 0) { gwlist_produce(incoming_wdp, msg); counter_increase(incoming_wdp_counter); } else { gwlist_produce(outgoing_wdp, msg); counter_increase(outgoing_wdp_counter); } octstr_destroy(cliaddr); octstr_destroy(ip); } gwlist_remove_producer(incoming_wdp); gwlist_remove_producer(flow_threads); }
unsigned write_available() const { return size() - read_available(); }