static void sig_exec_input_reader(PROCESS_REC *rec) { char tmpbuf[512], *str; unsigned int recvlen; int err, ret; g_return_if_fail(rec != NULL); recvlen = 0; err = g_io_channel_read(rec->in, tmpbuf, sizeof(tmpbuf), &recvlen); if (err != 0 && err != G_IO_ERROR_AGAIN && errno != EINTR) recvlen = -1; do { ret = line_split(tmpbuf, recvlen, &str, &rec->databuf); if (ret == -1) { /* link to terminal closed? */ g_source_remove(rec->read_tag); rec->read_tag = -1; break; } if (ret > 0) { signal_emit_id(signal_exec_input, 2, rec, str); if (recvlen > 0) recvlen = 0; } } while (ret > 0); }
static gboolean listen_from_server(GIOChannel *io, GIOCondition condition, void *cnt) { gchar buf[512]; gsize nbr; t_message msg; debug("listen_from_server()"); (void) condition; if (g_io_channel_read(io, buf, CLIENT_READ_BUF_SIZE, &nbr) != G_IO_ERROR_NONE) { g_io_channel_close(io); return (-1); } buf[nbr] = '\0'; if (nbr > 0) { extract_msg((char *) buf, &msg); printf("[%s]\n", msg.command); mesg_init(cnt, &msg); insert_mesg_to_list(cnt, EMPTY, "server", trim(buf)); } scrolled_window(cnt, SCROLL_MESG); g_io_add_watch(io, G_IO_IN, listen_from_server, cnt); return (0); }
static GIOError read_all (int fd, GIOChannel *channel, char *buffer, guint nbytes, guint *bytes_read) { guint left = nbytes; gsize nb; GIOError error = G_IO_ERROR_NONE; char *bufp = buffer; /* g_io_channel_read() doesn't necessarily return all the * data we want at once. */ *bytes_read = 0; while (left) { error = g_io_channel_read (channel, bufp, left, &nb); if (error != G_IO_ERROR_NONE) { g_print ("gio-test: ...from %d: %d\n", fd, error); if (error == G_IO_ERROR_AGAIN) continue; break; } if (nb == 0) return error; left -= nb; bufp += nb; *bytes_read += nb; } return error; }
static gboolean channel_process_input () { static char linebuf[4096]; char *linep = linebuf; char *line; int bytes_read; #if GLIB_MAJOR_VERSION > 1 // we need to call this again because we will get new events before returning // from this function // semantics of add_watch silently changing between glib versions!!!! g_io_add_watch (channel_in, G_IO_IN, (GIOFunc) channel_process_input, NULL); #endif g_io_channel_read (channel_in, linebuf, 4096, &bytes_read); linebuf[bytes_read] = '\0'; while (*linep != '\0') { line = linep; while (*linep++ != '\n') g_assert (linep[-1] != '\0'); linep[-1] = '\0'; if (opt_verbose) printf ("engine got command \"%s\"\n", line); command_list = g_slist_append (command_list, g_strdup (line)); } while (process_line ()) ; #if GLIB_MAJOR_VERSION == 1 return TRUE; #else return FALSE; #endif }
static gboolean recv_windows_message (GIOChannel *channel, GIOCondition cond, gpointer data) { GIOError error; MSG msg; guint nb; while (1) { error = g_io_channel_read (channel, &msg, sizeof (MSG), &nb); if (error != G_IO_ERROR_NONE) { g_print ("gio-test: ...reading Windows message: G_IO_ERROR_%s\n", (error == G_IO_ERROR_AGAIN ? "AGAIN" : (error == G_IO_ERROR_INVAL ? "INVAL" : (error == G_IO_ERROR_UNKNOWN ? "UNKNOWN" : "???")))); if (error == G_IO_ERROR_AGAIN) continue; } break; } g_print ("gio-test: ...Windows message for %#x: %d,%d,%d\n", msg.hwnd, msg.message, msg.wParam, msg.lParam); return TRUE; }
static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data) { char buf[BUF_SIZE]; struct serial_proxy *prx = data; GIOChannel *dest; GIOError err; size_t rbytes; if (cond & G_IO_NVAL) return FALSE; dest = (chan == prx->rfcomm) ? prx->local : prx->rfcomm; if (cond & (G_IO_HUP | G_IO_ERR)) { /* Try forward remaining data */ do { rbytes = 0; err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes); if (err != G_IO_ERROR_NONE || rbytes == 0) break; err = channel_write(dest, buf, rbytes); } while (err == G_IO_ERROR_NONE); g_io_channel_shutdown(prx->local, TRUE, NULL); g_io_channel_unref(prx->local); prx->local = NULL; g_io_channel_shutdown(prx->rfcomm, TRUE, NULL); g_io_channel_unref(prx->rfcomm); prx->rfcomm = NULL; return FALSE; } rbytes = 0; err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes); if (err != G_IO_ERROR_NONE) return FALSE; err = channel_write(dest, buf, rbytes); if (err != G_IO_ERROR_NONE) return FALSE; return TRUE; }
gboolean channel_pass_filename_callback(GIOChannel *source, GIOCondition condition, gpointer data ) { guint size; gchar buf[1024]; g_io_channel_read(inter_gphpedit_io, buf, sizeof(buf), &size); //g_print("Passed %s\n", buf); tab_create_new(TAB_FILE, g_string_new(buf)); return FALSE; }
static GIOError gst_avdtp_sink_audioservice_recv( GstAvdtpSink *self, bt_audio_msg_header_t *inmsg) { GIOError status; gsize bytes_read; const char *type, *name; uint16_t length; length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE; status = g_io_channel_read(self->server, (gchar *) inmsg, length, &bytes_read); if (status != G_IO_ERROR_NONE) { GST_ERROR_OBJECT(self, "Error receiving data from " "audio service"); return status; } type = bt_audio_strtype(inmsg->type); if (!type) { status = G_IO_ERROR_INVAL; GST_ERROR_OBJECT(self, "Bogus message type %d " "received from audio service", inmsg->type); } name = bt_audio_strname(inmsg->name); if (!name) { status = G_IO_ERROR_INVAL; GST_ERROR_OBJECT(self, "Bogus message name %d " "received from audio service", inmsg->name); } if (inmsg->type == BT_ERROR) { bt_audio_error_t *err = (void *) inmsg; status = G_IO_ERROR_INVAL; GST_ERROR_OBJECT(self, "%s failed : " "%s(%d)", name, strerror(err->posix_errno), err->posix_errno); } GST_DEBUG_OBJECT(self, "received: %s <- %s", type, name); return status; }
static gboolean _monitor_input_cb(GIOChannel *channel) { gchar buf[MAX_STRING_LEN+3]; gsize len; g_io_channel_read(channel, buf, MAX_STRING_LEN, &len); buf[len] = 0x00; g_strstrip(buf); _monitor_parse_command(buf); return TRUE; }
static int g_io_channel_read_block(GIOChannel *channel, void *data, int len) { time_t maxwait; gsize ret; int err, received; maxwait = time(NULL)+2; received = 0; do { err = g_io_channel_read(channel, (char *) data + received, len-received, &ret); received += ret; } while (received < len && time(NULL) < maxwait && (ret != 0 || !is_fatal_error(err))); return received < len ? -1 : 0; }
/* Read data from socket, return number of bytes read, -1 = error */ int net_receive(GIOChannel *handle, char *buf, int len) { unsigned int ret; int err; g_return_val_if_fail(handle != NULL, -1); g_return_val_if_fail(buf != NULL, -1); err = g_io_channel_read(handle, buf, len, &ret); if (err == 0 && ret == 0) return -1; /* disconnected */ if (err == G_IO_ERROR_AGAIN || (err != 0 && errno == EINTR)) return 0; /* no bytes received */ return err == 0 ? (int)ret : -1; }
static gboolean handle_signal_pipe(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) { /* It can only be SIGCHLD. Therefore we do not check the result, * and eat more than one byte at once: why refresh twice? */ gchar buf[16]; gsize bytes_read; g_io_channel_read(gio, buf, sizeof(buf), &bytes_read); /* Destroy zombies */ while (waitpid(-1, NULL, WNOHANG) > 0) continue; rescan_and_refresh(); return TRUE; /* "please don't remove this event" */ }
static gboolean file_read_data (GIOChannel *iochannel, GIOCondition condition, gpointer user_data) { RCDTransfer *t = user_data; RCDTransferProtocolFile *protocol = (RCDTransferProtocolFile *) t->protocol; GIOError err; char buf[BLOCK_SIZE]; gsize bytes; if (!(condition & G_IO_IN)) goto ERROR; err = g_io_channel_read (iochannel, buf, BLOCK_SIZE, &bytes); if (bytes) rcd_transfer_emit_data (t, buf, bytes); if (err == G_IO_ERROR_AGAIN) return TRUE; if (err != G_IO_ERROR_NONE) goto ERROR; if (bytes > 0) { /* More data to read. Whee. */ return TRUE; } else { /* No more bytes to read and no error condition; the file is done */ g_io_channel_close (iochannel); rcd_transfer_emit_done (t); return FALSE; } ERROR: g_source_remove (protocol->watch); rcd_transfer_set_error (t, RCD_TRANSFER_ERROR_IO, NULL); rcd_transfer_emit_done (t); return FALSE; }
static gboolean session_event(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[672]; gsize len, written; GIOError err; if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) return FALSE; err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); if (err == G_IO_ERROR_AGAIN) return TRUE; g_io_channel_write(chan, (const gchar *) buf, len, &written); return TRUE; }
static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; evt_stack_internal *si; evt_si_device *sd; hci_event_hdr *eh; int type; size_t len; GIOError err; ptr = buf; err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); if (err) { if (err == G_IO_ERROR_AGAIN) return TRUE; error("Read from control socket failed: %s (%d)", strerror(errno), errno); return FALSE; } type = *ptr++; if (type != HCI_EVENT_PKT) return TRUE; eh = (hci_event_hdr *) ptr; if (eh->evt != EVT_STACK_INTERNAL) return TRUE; ptr += HCI_EVENT_HDR_SIZE; si = (evt_stack_internal *) ptr; switch (si->type) { case EVT_SI_DEVICE: sd = (void *) &si->data; device_event(sd->event, sd->dev_id); break; } return TRUE; }
static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct fake_input *fake = data; const char *ok = "\r\nOK\r\n"; char buf[BUF_SIZE]; gsize bread = 0, bwritten; uint16_t key; if (cond & G_IO_NVAL) return FALSE; if (cond & (G_IO_HUP | G_IO_ERR)) { error("Hangup or error on rfcomm server socket"); goto failed; } memset(buf, 0, BUF_SIZE); if (g_io_channel_read(chan, buf, sizeof(buf) - 1, &bread) != G_IO_ERROR_NONE) { error("IO Channel read error"); goto failed; } DBG("Received: %s", buf); if (g_io_channel_write(chan, ok, 6, &bwritten) != G_IO_ERROR_NONE) { error("IO Channel write error"); goto failed; } key = decode_key(buf); if (key != KEY_RESERVED) send_key(fake->uinput, key); return TRUE; failed: ioctl(fake->uinput, UI_DEV_DESTROY); close(fake->uinput); fake->uinput = -1; g_io_channel_unref(fake->io); return FALSE; }
/* Inotify handler */ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) { /* Since dump dir creation usually involves directory rename as a last step, * we end up rescanning twice. A small wait after first inotify event * usually allows to avoid this. */ usleep(10*1000); /* We read inotify events, but don't analyze them */ gchar buf[sizeof(struct inotify_event) + PATH_MAX + 64]; gsize bytes_read; while (g_io_channel_read(gio, buf, sizeof(buf), &bytes_read) == G_IO_ERROR_NONE && bytes_read > 0 ) { continue; } rescan_and_refresh(); return TRUE; /* "please don't remove this event" */ }
static gboolean recv_windows_message (GIOChannel *channel, GIOCondition cond, gpointer data) { GIOError error; MSG msg; guint nb; while (1) { error = g_io_channel_read (channel, &msg, sizeof (MSG), &nb); if (error != G_IO_ERROR_NONE) { if (error == G_IO_ERROR_AGAIN) continue; } break; } return TRUE; }
static gboolean script_fu_siod_read (GIOChannel *channel, GIOCondition cond, gpointer data) { int count; static int hack = 0; GIOError error; count = 0; error = g_io_channel_read (channel, read_buffer, BUFSIZE - 1, &count); if (error == G_IO_ERROR_NONE) { #ifndef G_OS_WIN32 /* Is this needed any longer on Unix? */ if (!hack) /* this is a stupid hack, but as of 10/27/98 * the script-fu-console will hang on my system without it. * the real cause of this needs to be tracked down. * posibly a problem with the text widget, or the * signal handlers not getting fully initialized or... * no reports of hangs on other platforms, could just be a * problem with my system. */ { hack = 1; return TRUE; } #endif read_buffer[count] = '\0'; gtk_text_freeze (GTK_TEXT (cint.console)); gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL, read_buffer, -1); gtk_text_thaw (GTK_TEXT (cint.console)); script_fu_console_scroll_end (NULL); } return TRUE; }
static gboolean io_hci_data(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; int type; gsize len; GIOError err; ptr = buf; if ((err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len))) { if (err == G_IO_ERROR_AGAIN) return TRUE; syslog(LOG_ERR, "Read failed: %s (%d)", strerror(errno), errno); g_io_channel_unref(chan); g_main_loop_quit(event_loop); return FALSE; } type = *ptr++; write_snoop(vdev.dd, type, 0, buf, len); switch (type) { case HCI_COMMAND_PKT: hci_command(ptr); break; case HCI_ACLDATA_PKT: hci_acl_data(ptr); break; default: syslog(LOG_ERR, "Unknown packet type 0x%2.2x", type); break; } return TRUE; }
static gboolean read_all (GIOChannel *channel, char *buf, int len) { gsize bytes_read = 0; gsize count; GIOError err; while (bytes_read < len) { err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count); if (err) { if (err != G_IO_ERROR_AGAIN) return FALSE; } else if (count == 0) return FALSE; bytes_read += count; } return TRUE; }
static gboolean session_event(GIOChannel *chan, GIOCondition cond, gpointer data) { struct dun_server *server = data; unsigned char buf[672]; gsize len, written; GIOError err; if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) goto disconnected; err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); if (err == G_IO_ERROR_AGAIN) return TRUE; g_io_channel_write(chan, (const gchar *) buf, len, &written); return TRUE; disconnected: server->client_id = 0; disconnect(server); return FALSE; }
static gboolean sock_get_address_info_async_cb(GIOChannel *source, GIOCondition condition, gpointer data) { SockLookupData *lookup_data = (SockLookupData *)data; GList *addr_list = NULL; SockAddrData *addr_data; gsize bytes_read; gint ai_member[4]; struct sockaddr *addr; for (;;) { if (g_io_channel_read(source, (gchar *)ai_member, sizeof(ai_member), &bytes_read) != G_IO_ERROR_NONE) { g_warning("sock_get_address_info_async_cb: " "address length read error\n"); break; } if (bytes_read == 0 || bytes_read != sizeof(ai_member)) break; if (ai_member[0] == AF_UNSPEC) { g_warning("DNS lookup failed\n"); break; } addr = g_malloc(ai_member[3]); if (g_io_channel_read(source, (gchar *)addr, ai_member[3], &bytes_read) != G_IO_ERROR_NONE) { g_warning("sock_get_address_info_async_cb: " "address data read error\n"); g_free(addr); break; } if (bytes_read != ai_member[3]) { g_warning("sock_get_address_info_async_cb: " "incomplete address data\n"); g_free(addr); break; } addr_data = g_new0(SockAddrData, 1); addr_data->family = ai_member[0]; addr_data->socktype = ai_member[1]; addr_data->protocol = ai_member[2]; addr_data->addr_len = ai_member[3]; addr_data->addr = addr; addr_list = g_list_append(addr_list, addr_data); } g_io_channel_shutdown(source, FALSE, NULL); g_io_channel_unref(source); sock_kill_process(lookup_data->child_pid); lookup_data->func(addr_list, lookup_data->data); g_free(lookup_data->hostname); g_free(lookup_data); return FALSE; }
static gboolean rfkill_event(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[32]; struct rfkill_event *event = (void *) buf; struct btd_adapter *adapter; char sysname[PATH_MAX]; gsize len; GIOError err; int fd, id; if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) return FALSE; memset(buf, 0, sizeof(buf)); err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); if (err) { if (err == G_IO_ERROR_AGAIN) return TRUE; return FALSE; } if (len != sizeof(struct rfkill_event)) return TRUE; debug("RFKILL event idx %u type %u op %u soft %u hard %u", event->idx, event->type, event->op, event->soft, event->hard); if (event->soft || event->hard) return TRUE; if (event->op != RFKILL_OP_CHANGE) return TRUE; if (event->type != RFKILL_TYPE_BLUETOOTH && event->type != RFKILL_TYPE_ALL) return TRUE; snprintf(sysname, sizeof(sysname) - 1, "/sys/class/rfkill/rfkill%u/name", event->idx); fd = open(sysname, O_RDONLY); if (fd < 0) return TRUE; memset(sysname, 0, sizeof(sysname)); if (read(fd, sysname, sizeof(sysname)) < 4) { close(fd); return TRUE; } close(fd); if (g_str_has_prefix(sysname, "hci") == FALSE) return TRUE; id = atoi(sysname + 3); if (id < 0) return TRUE; adapter = manager_find_adapter_by_id(id); if (!adapter) return TRUE; debug("RFKILL unblock for hci%d", id); btd_adapter_restore_powered(adapter); return TRUE; }
static gboolean gst_avdtp_sink_conf_recv_stream_fd( GstAvdtpSink *self) { struct bluetooth_data *data = self->data; gint ret; GIOError err; GError *gerr = NULL; GIOStatus status; GIOFlags flags; gsize read; ret = gst_avdtp_sink_bluetooth_recvmsg_fd(self); if (ret < 0) return FALSE; if (!self->stream) { GST_ERROR_OBJECT(self, "Error while configuring device: " "could not acquire audio socket"); return FALSE; } /* set stream socket to nonblock */ GST_LOG_OBJECT(self, "setting stream socket to nonblock"); flags = g_io_channel_get_flags(self->stream); flags |= G_IO_FLAG_NONBLOCK; status = g_io_channel_set_flags(self->stream, flags, &gerr); if (status != G_IO_STATUS_NORMAL) { if (gerr) GST_WARNING_OBJECT(self, "Error while " "setting server socket to nonblock: " "%s", gerr->message); else GST_WARNING_OBJECT(self, "Error while " "setting server " "socket to nonblock"); } /* It is possible there is some outstanding data in the pipe - we have to empty it */ GST_LOG_OBJECT(self, "emptying stream pipe"); while (1) { err = g_io_channel_read(self->stream, data->buffer, (gsize) data->link_mtu, &read); if (err != G_IO_ERROR_NONE || read <= 0) break; } /* set stream socket to block */ GST_LOG_OBJECT(self, "setting stream socket to block"); flags = g_io_channel_get_flags(self->stream); flags &= ~G_IO_FLAG_NONBLOCK; status = g_io_channel_set_flags(self->stream, flags, &gerr); if (status != G_IO_STATUS_NORMAL) { if (gerr) GST_WARNING_OBJECT(self, "Error while " "setting server socket to block:" "%s", gerr->message); else GST_WARNING_OBJECT(self, "Error while " "setting server " "socket to block"); } memset(data->buffer, 0, sizeof(data->buffer)); return TRUE; }
static int xchat_read_fd (xchat_plugin *ph, GIOChannel *source, char *buf, int *len) { return g_io_channel_read (source, buf, *len, len); }
static gboolean ps3remote_event(GIOChannel *chan, GIOCondition cond, gpointer data) { struct fake_input *fake = data; struct uinput_event event; unsigned int key, value = 0; gsize size; char buff[50]; if (cond & G_IO_NVAL) return FALSE; if (cond & (G_IO_HUP | G_IO_ERR)) { error("Hangup or error on rfcomm server socket"); goto failed; } memset(buff, 0, sizeof(buff)); if (g_io_channel_read(chan, buff, sizeof(buff), &size) != G_IO_ERROR_NONE) { error("IO Channel read error"); goto failed; } key = ps3remote_decode(buff, size, &value); if (key == KEY_RESERVED) { error("Got invalid key from decode"); goto failed; } else if (key == KEY_MAX) return TRUE; memset(&event, 0, sizeof(event)); gettimeofday(&event.time, NULL); event.type = EV_KEY; event.code = key; event.value = value; if (write(fake->uinput, &event, sizeof(event)) != sizeof(event)) { error("Error writing to uinput device"); goto failed; } memset(&event, 0, sizeof(event)); gettimeofday(&event.time, NULL); event.type = EV_SYN; event.code = SYN_REPORT; if (write(fake->uinput, &event, sizeof(event)) != sizeof(event)) { error("Error writing to uinput device"); goto failed; } return TRUE; failed: ioctl(fake->uinput, UI_DEV_DESTROY); close(fake->uinput); fake->uinput = -1; g_io_channel_unref(fake->io); return FALSE; }
/* This callback is called for (IN|ERR) or OUT. We add the watch for (IN|ERR) when the client connects in async_server_iofunc(). We remove it if the connection is closed (i.e. we read 0 bytes) or if there's an error. We add the watch for OUT when we have something to write and remove it when we're done writing or when the connection is closed. */ static gboolean async_client_iofunc(GIOChannel *iochannel, GIOCondition c, gpointer data) { client_state *cs = (client_state *) data; g_assert(cs != NULL); /* Check for socket error */ if (c & G_IO_ERR) { fprintf(stderr, "Client socket error!\n"); goto error; } /* Check for data to be read (or if the socket was closed) */ if (c & G_IO_IN) { GIOError e; gsize bytes_read; /* Read the data into our buffer */ e = g_io_channel_read(iochannel, &cs->buffer[cs->n], sizeof(cs->buffer) - cs->n, &bytes_read); /* Check for socket error */ if (e != G_IO_ERROR_NONE) { fprintf(stderr, "Client read error: %d\n", e); goto error; } else if (bytes_read == 0) { /* Check if we read 0 bytes, which means the connection is closed */ goto error; } else { g_assert(bytes_read > 0); /* If there isn't an out_watch, add one */ if (cs->out_watch == 0) { cs->out_watch = g_io_add_watch(iochannel, G_IO_OUT, async_client_iofunc, cs); } if (fwrite(&cs->buffer[cs->n], bytes_read, 1, stdout) != 1) { fprintf (stderr, "Error: fwrite to stdout failed: %s\n", g_strerror (errno)); } cs->n += bytes_read; } } if (c & G_IO_OUT) { GIOError e; gsize bytes_written; /* Write the data out */ e = g_io_channel_write(iochannel, cs->buffer, cs->n, &bytes_written); if (e != G_IO_ERROR_NONE) { fprintf(stderr, "Client write error: %d\n", e); clientstate_delete(cs); return FALSE; } else if (bytes_written > 0) { /* Move the memory down some (you wouldn't do this in a performance server because it's slow) */ g_memmove(cs->buffer, &cs->buffer[bytes_written], bytes_written); cs->n -= bytes_written; } /* Check if done */ if (cs->n == 0) { cs->out_watch = 0; return FALSE; } } return TRUE; error: clientstate_delete(cs); return FALSE; }
guint http_request_read (http_request *h) { gchar *buf = g_new( gchar, BUFSIZ + 1 ); /* GIOStatus r; GError *err = NULL; */ GIOError r; guint s, times, n = 0, t = 0; gchar *c_len_hdr = NULL; guint hdr_len = 0, c_len = 0, tot_req_size = 0; struct timeval tv; fd_set fdset; FD_ZERO(&fdset); FD_SET(g_io_channel_unix_get_fd(h->sock), &fdset); tv.tv_sec = 0; buf[0] = '\0'; buf[BUFSIZ] = '\0'; // for (t = 0, n = BUF_SIZ; n == BUF_SIZ && // h->buffer->len < MAX_REQUEST_SIZE; t += n ) { // BPsmythe: The above (original) loop will never execute // more than once unless the size of the buffer read in (n) // is equal to the constant BUF_SIZE. What is desired is // to keep looping until there is nothing left to read. // The for was changed to look for the end of the headers. // FIXME: We should use the newer g_io_channel_read_char // // TJaqua: Added buffer overflow checking, content read loop from 0.93pre2, and fixed up the timeouts, logging and error exits if (CONFd("Verbosity") >= 7) g_message("http_request_read: READING request from peer %s (on %s, fd: %d)", h->peer_ip, h->sock_ip, g_io_channel_unix_get_fd(h->sock)); if (CONFd("Verbosity") >= 9) g_message("http_request_read: entering HEADER read loop (BUFSIZE=%u)", BUFSIZ); for (times=MAX_REQ_TIMEOUTS; !hdr_len && (times > 0); t += n ) { n=0; /* r = g_io_channel_read_chars( h->sock, buf, BUFSIZ, &n, &err ); if (r == G_IO_STATUS_ERROR || err != NULL) { g_message( "http_request_read: Socket IO ERROR: %s, exiting!", err->message ); g_error_free(err); */ r = g_io_channel_read( h->sock, buf, BUFSIZ, &n); if (r != G_IO_ERROR_NONE) { g_warning( "http_request_read: Socket IO ERROR: %m, exiting!" ); g_free(buf); return 0; } if (CONFd("Verbosity") >= 9) g_message("http_request_read: HEADER loop read %u bytes", n); buf[n] = '\0'; if (n && CONFd("Verbosity") >= 11) syslog_message("RAW_HDR_BUF: ", buf, n); if(strlen(buf) < n-1) g_warning("http_request_read: Trailing data past string in buffer was DICARDED!"); if (h->buffer->len == MAX_REQUEST_SIZE) g_warning("http_request_read: header buffer full (%u bytes, %u bytes discarded!)", MAX_REQUEST_SIZE, n); else if (n <= (MAX_REQUEST_SIZE - h->buffer->len)) { if(CONFd("Verbosity") >= 11) g_message("http_request_read: APPENDING buffer to HEADER."); if(n) g_string_append(h->buffer, buf); else if (CONFd("Verbosity") >= 6) g_message("http_request_read: No data in buffer."); //if(CONFd("Verbosity") >= 11) g_message("http_request_read: Partial HEADER (%u bytes) is: %s", h->buffer->len, h->buffer->str); } else { if(CONFd("Verbosity") >= 6) g_warning("http_request_read: header buffer full (%u bytes, %u bytes discarded!)", MAX_REQUEST_SIZE, n - (MAX_REQUEST_SIZE - h->buffer->len)); buf[MAX_REQUEST_SIZE - h->buffer->len] = '\0'; g_string_append(h->buffer, buf); } times--; // BPsmythe: Check for the end of the headers. if (hdr_len = http_get_hdr_len(h->buffer->str)) { if (CONFd("Verbosity") >= 6) g_message("http_request_read: HEADER END found, length: %u", hdr_len ); } else { if(!times) { if(CONFd("Verbosity") >= 6) { g_message("http_request_read: ERROR: HEADER END not found after %d tries, exiting!", MAX_REQ_TIMEOUTS); if (!t) g_message("http_request_read: Empty HTTP-request header."); else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n); } //Should I send a FIN packet to shutdown the socket? g_free(buf); return 0; } if(CONFd("Verbosity") >= 11) g_message("http_request_read: Waiting for next I/O on socket, (%d more tries).", times); tv.tv_usec = REQ_TIMEOUT; while(times && !(s = select (g_io_channel_unix_get_fd(h->sock)+1, &fdset, NULL, NULL, &tv))) { times--; if (CONFd("Verbosity") >= 7) g_message("http_request_read: HEADER select timeout, %d more tries", times); tv.tv_usec = REQ_TIMEOUT; } if(s<0) { g_warning("http_request_read: ERROR in select, exiting!"); g_free(buf); return 0; } else if(!times) { if(CONFd("Verbosity") >= 6) { g_message("http_request_read: ERROR: Too many TIMEOUTS waiting for HEADER end!"); if (!t) g_message("http_request_read: Empty HTTP-request header."); else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n); } //Should I send a FIN packet to shutdown the socket? g_free(buf); return 0; } else if(CONFd("Verbosity") >= 11) g_message("http_request_read: Recieved I/O on socket."); } } if (CONFd("Verbosity") >= 10) syslog_message("RAW_HEADER: ", h->buffer->str, h->buffer->len); // Read the content length from the header http_parse_header( h, h->buffer->str ); if( (HEADER("Content-length")) && (c_len = atoi(HEADER("Content-length"))) ) { if (CONFd("Verbosity") >= 9) g_message("http_request_read: entering CONTENT read loop to read %u bytes.", c_len); tot_req_size = hdr_len + c_len; for (times=MAX_REQ_TIMEOUTS; (t < tot_req_size) && (times > 0); t += n ) { if (CONFd("Verbosity") >= 9) g_message("http_request_read: %u bytes of %u total.", t, tot_req_size ); n=0; /* r = g_io_channel_read_chars( h->sock, buf, BUFSIZ, &n, &err ); if (r == G_IO_STATUS_ERROR || err != NULL) { g_message( "http_request_read: Socket-IO ERROR: %s, exiting!", err->message ); g_error_free(err); */ r = g_io_channel_read( h->sock, buf, BUFSIZ, &n); if (r != G_IO_ERROR_NONE) { g_warning( "http_request_read: Socket-IO ERROR: %m, exiting!" ); g_free(buf); return 0; } if (CONFd("Verbosity") >= 9) g_message("http_request_read: CONTENT loop read %d bytes", n ); buf[n] = '\0'; if (n && CONFd("Verbosity") >= 11) syslog_message("RAW_CON_BUF: ", buf, n); if (h->buffer->len == MAX_REQUEST_SIZE) { if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Maximum request length EXCEEDED (%u bytes discarded! Continuing to read out content.)", n); } else if (h->buffer->len == tot_req_size) { if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Content length EXCEEDED (%u bytes discarded! Shouldn't happen!)", n); } else if (h->buffer->len + n >= MAX_REQUEST_SIZE) { if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Max buffer length EXCEEDED (%u bytes discarded! Continuing to read out content.)", n - (MAX_REQUEST_SIZE - h->buffer->len)); buf[MAX_REQUEST_SIZE - h->buffer->len] = '\0'; g_string_append(h->buffer, buf); } else if (n <= (tot_req_size - h->buffer->len)) { if(CONFd("Verbosity") >= 11) g_message("http_request_read: APPENDING buffer to CONTENT."); if(n) g_string_append(h->buffer, buf); else if (CONFd("Verbosity") >= 6) g_message("http_request_read: No data in buffer."); } else { if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Content length EXCEEDED (%u bytes added, %u bytes discarded!)", tot_req_size - h->buffer->len, n - (tot_req_size - h->buffer->len)); buf[tot_req_size - h->buffer->len] = '\0'; g_string_append(h->buffer, buf); } times--; // TJaqua: Check for the end of the content. if ((t+n) >= tot_req_size) { if (CONFd("Verbosity") >= 6) g_message("http_request_read: CONTENT end reached, length: %u", tot_req_size); } else { if (!times) { if(CONFd("Verbosity") >= 6) { g_message("http_request_read: ERROR: CONTENT END not found after %d tries, exiting!", MAX_REQ_TIMEOUTS); if (t == hdr_len) g_message("http_request_read: Empty CONTENT, socket may have stalled."); else g_message("http_request_read: CONTENT unfinished, %u bytes read.", t+n); } //Should I send a FIN packet to shutdown the socket? g_free(buf); //We still got the header, though, so return it. g_string_truncate(h->buffer, hdr_len); return hdr_len; } if(CONFd("Verbosity") >= 11) g_message("http_request_read: Waiting for next I/O on socket."); tv.tv_usec = REQ_TIMEOUT; while (times && !(s = select (g_io_channel_unix_get_fd(h->sock)+1, &fdset, NULL, NULL, &tv))) { times--; if (CONFd("Verbosity") >= 7) g_message("http_request_read: CONTENT select timeout, %d more tries", times); tv.tv_usec = REQ_TIMEOUT; } if(s<0) { g_warning("http_request_read: ERROR in select, exiting!"); g_free(buf); //We still got the header, though, so return it. g_string_truncate(h->buffer, hdr_len); return hdr_len; } else if (!times) { if(CONFd("Verbosity") >= 6) { g_message("http_request_read: ERROR: Too many TIMEOUTS waiting for CONTENT end!"); if (t == hdr_len) g_message("http_request_read: Empty CONTENT, socket may have stalled."); else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n); } //Should I send a FIN packet to shutdown the socket? g_free(buf); //We still got the header, though, so return it. g_string_truncate(h->buffer, hdr_len); return hdr_len; } else if (CONFd("Verbosity") >= 11) g_message("http_request_read: Received I/O on socket."); } } if (CONFd("Verbosity") >= 10) syslog_message("RAW_CONTENT: ", &(h->buffer->str[hdr_len]), h->buffer->len - hdr_len); if (t<tot_req_size) g_message("http_request_read: CONTENT unfinished - should not happen!"); } if (CONFd("Verbosity") >= 6) g_message("http_request_read: FINISHED read (%u bytes total), exiting.", t); g_free(buf); return t; }
static gboolean rc_line_buf_cb (GIOChannel *source, GIOCondition condition, gpointer data) { RCLineBuf *line_buf = (RCLineBuf *)data; gsize bytes_read; guint count; guint base = 0; gchar buf[BUF_SIZE + 1]; if (condition & (G_IO_IN | G_IO_PRI)) { switch (g_io_channel_read (source, buf, BUF_SIZE, &bytes_read)) { case G_IO_ERROR_AGAIN: /* This really shouldn't happen; why on earth would we get called if there's no data waiting? */ rc_debug (RC_DEBUG_LEVEL_WARNING, "%s: got G_IO_ERROR_AGAIN, bork bork?\n", __FUNCTION__); return (TRUE); case G_IO_ERROR_INVAL: case G_IO_ERROR_UNKNOWN: /* Whoops, this is bad */ rc_debug (RC_DEBUG_LEVEL_ERROR, "%s: got G_IO_ERROR_[INVAL|UNKNOWN], ending read\n", __FUNCTION__); g_signal_emit (line_buf, signals[READ_DONE], 0, RC_LINE_BUF_ERROR); /* I don't think I should have to do this, but this is the solution to the infamous big bad oh-what-the-f**k bug, so... */ g_source_remove (line_buf->priv->cb_id); line_buf->priv->cb_id = 0; return (FALSE); case G_IO_ERROR_NONE: if (bytes_read == 0) { /* A read of 0 bytes with no error means we're done * here */ #if 0 rc_debug (RC_DEBUG_LEVEL_DEBUG, "%s: read 0 bytes, we're done here\n", __FUNCTION__); #endif g_signal_emit (line_buf, signals[READ_DONE], 0, RC_LINE_BUF_OK); /* I don't think I should have to do this, but this is the solution to the infamous big bad oh-what-the-f**k bug, so */ g_source_remove (line_buf->priv->cb_id); line_buf->priv->cb_id = 0; return (FALSE); } #if 0 rc_debug (RC_DEBUG_LEVEL_DEBUG, "%s: read %d bytes\n", __FUNCTION__, bytes_read); #endif buf[bytes_read] = '\0'; for (count = 0; count < bytes_read; count++) { if (buf[count] == '\n') { buf[count] = '\0'; if (count && buf[count - 1] == '\r') { buf[count - 1] = '\0'; } line_buf->priv->buf = g_string_append (line_buf->priv->buf, buf + base); #if 0 rc_debug (RC_DEBUG_LEVEL_DEBUG, __FUNCTION__ ": line is \"%s\"\n", line_buf->priv->buf->str); #endif g_signal_emit (line_buf, signals[READ_LINE], 0, line_buf->priv->buf->str); g_string_truncate (line_buf->priv->buf, 0); base = count + 1; } } line_buf->priv->buf = g_string_append (line_buf->priv->buf, buf + base); return (TRUE); } } else { g_signal_emit (line_buf, signals[READ_DONE], 0, RC_LINE_BUF_OK); g_source_remove (line_buf->priv->cb_id); line_buf->priv->cb_id = 0; #if 0 rc_debug (RC_DEBUG_LEVEL_DEBUG, "%s: got G_IO_[(HUP)|(ERR)], we're " "done here\n", __FUNCTION__); #endif return (FALSE); } g_assert_not_reached (); return (FALSE); } /* rc_line_buf_cb */