2000-12-09 Kevin L. Mitchell <klmitch@mit.edu>
+ * ircd/send.c (send_queued): call deliver_it with appropriate
+ arguments
+
+ * ircd/s_serv.c: reorder a couple of headers--cosmetic
+
+ * ircd/s_bsd.c (deliver_it): make deliver_it work with a struct
+ MsgQ
+
+ * ircd/os_solaris.c (os_sendv_nonb): function for calling writev
+ with appropriate iovec
+
+ * ircd/os_linux.c (os_sendv_nonb): function for calling writev
+ with appropriate iovec
+
+ * ircd/os_generic.c (os_sendv_nonb): function for calling writev
+ with appropriate iovec
+
+ * ircd/os_bsd.c (os_sendv_nonb): function for calling writev with
+ appropriate iovec
+
+ * ircd/msgq.c (msgq_mapiov): add a len_p argument for totalling up
+ exactly how much we're trying to write out to the fd
+
+ * include/s_bsd.h: make deliver_it take a struct MsgQ
+
+ * include/msgq.h: add a len_p argument to msgq_mapiov to help
+ detect short writes that indicate possible socket blocking
+
+ * include/ircd_osdep.h: declare os_sendv_nonb()
+
* ircd/channel.c (modebuf_mode): don't add empty modes...
2000-12-08 Kevin L. Mitchell <klmitch@mit.edu>
struct Client;
struct sockaddr_in;
+struct MsgQ;
typedef enum IOResult {
IO_FAILURE = -1,
unsigned int* length_out);
extern IOResult os_send_nonb(int fd, const char* buf, unsigned int length,
unsigned int* length_out);
+extern IOResult os_sendv_nonb(int fd, struct MsgQ* buf,
+ unsigned int* len_in, unsigned int* len_out);
extern IOResult os_recvfrom_nonb(int fd, char* buf, unsigned int len,
unsigned int* length_out,
struct sockaddr_in* from_out);
extern void msgq_init(struct MsgQ *mq);
extern void msgq_delete(struct MsgQ *mq, unsigned int length);
extern const char *msgq_map(const struct MsgQ *mq, unsigned int *length_p);
-extern int msgq_mapiov(const struct MsgQ *mq, struct iovec *iov, int count);
+extern int msgq_mapiov(const struct MsgQ *mq, struct iovec *iov, int count,
+ unsigned int *len);
extern struct MsgBuf *msgq_make(struct Client *dest, const char *format, ...);
extern struct MsgBuf *msgq_vmake(struct Client *dest, const char *format,
va_list args);
struct ConfItem;
struct Listener;
struct DNSReply;
+struct MsgQ;
/*
* TCP window sizes
/*
* Proto types
*/
-extern unsigned int deliver_it(struct Client *cptr, const char *str, unsigned int len);
+extern unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf);
extern int connect_server(struct ConfItem* aconf, struct Client* by,
struct DNSReply* reply);
extern void release_dns_reply(struct Client* cptr);
* struct iovec's.
*/
int
-msgq_mapiov(const struct MsgQ *mq, struct iovec *iov, int count)
+msgq_mapiov(const struct MsgQ *mq, struct iovec *iov, int count,
+ unsigned int *len)
{
struct Msg *queue;
struct Msg *prio;
assert(0 != mq);
assert(0 != iov);
assert(0 != count);
+ assert(0 != len);
if (mq->length <= 0) /* no data to map */
return 0;
if (mq->queue.head && mq->queue.head->sent > 0) { /* partial msg on norm q */
iov[i].iov_base = mq->queue.head->msg->msg + mq->queue.head->sent;
iov[i].iov_len = mq->queue.head->msg->length - mq->queue.head->sent;
+ *len += iov[i].iov_len;
queue = mq->queue.head->next; /* where we start later... */
if (mq->prio.head && mq->prio.head->sent > 0) { /* partial msg on prio q */
iov[i].iov_base = mq->prio.head->msg->msg + mq->prio.head->sent;
iov[i].iov_len = mq->prio.head->msg->length - mq->prio.head->sent;
+ *len += iov[i].iov_len;
prio = mq->prio.head->next; /* where we start later... */
for (; prio; prio = prio->next) { /* go through prio queue */
iov[i].iov_base = prio->msg->msg; /* store message */
iov[i].iov_len = prio->msg->length;
+ *len += iov[i].iov_len;
i++; /* filled an iovec... */
if (!--count) /* check for space */
for (; queue; queue = queue->next) { /* go through normal queue */
iov[i].iov_base = queue->msg->msg;
iov[i].iov_len = queue->msg->length;
+ *len += iov[i].iov_len;
i++; /* filled an iovec... */
if (!--count) /* check for space */
* $Id$
*
*/
+#define _XOPEN_SOURCE /* make limits.h #define IOV_MAX */
+
#include "ircd_osdep.h"
#include "config.h"
+#include "msgq.h"
#include <assert.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
+#include <limits.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <unistd.h>
#ifdef HPUX
return IO_FAILURE;
}
+IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in,
+ unsigned int* count_out)
+{
+ int res;
+ int count;
+ struct iovec iov[IOV_MAX];
+
+ assert(0 != buf);
+ assert(0 != count_in);
+ assert(0 != count_out);
+
+ *count_in = 0;
+ *count_out = 0;
+ errno = 0;
+
+ count = msgq_mapiov(buf, iov, IOV_MAX, count_in);
+
+ if (-1 < (res = writev(fd, iov, count))) {
+ *count_out = (unsigned) res;
+ return IO_SUCCESS;
+ }
+ else if (EWOULDBLOCK == errno || EAGAIN == errno ||
+ ENOMEM == errno || ENOBUFS == errno)
+ return IO_BLOCKED;
+
+ return IO_FAILURE;
+}
+
int os_connect_nonb(int fd, const struct sockaddr_in* sin)
{
if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) {
* $Id$
*
*/
+#define _XOPEN_SOURCE /* make limits.h #define IOV_MAX */
+
#include "ircd_osdep.h"
#include "config.h"
+#include "msgq.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/uio.h>
#if 0
#include <unistd.h>
return IO_FAILURE;
}
+IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in,
+ unsigned int* count_out)
+{
+ int res;
+ int count;
+ struct iovec iov[IOV_MAX];
+
+ assert(0 != buf);
+ assert(0 != count_in);
+ assert(0 != count_out);
+
+ *count_in = 0;
+ *count_out = 0;
+ errno = 0;
+
+ count = msgq_mapiov(buf, iov, IOV_MAX, count_in);
+
+ if (-1 < (res = writev(fd, iov, count))) {
+ *count_out = (unsigned) res;
+ return IO_SUCCESS;
+ }
+ else if (EWOULDBLOCK == errno || EAGAIN == errno ||
+ ENOMEM == errno || ENOBUFS == errno)
+ return IO_BLOCKED;
+
+ return IO_FAILURE;
+}
+
int os_connect_nonb(int fd, const struct sockaddr_in* sin)
{
if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) {
* $Id$
*
*/
+#define _XOPEN_SOURCE /* make limits.h #define IOV_MAX */
+
#include "ircd_osdep.h"
+#include "msgq.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/times.h>
+#include <sys/uio.h>
#include <sys/param.h>
#if 0
#include <unistd.h>
return IO_FAILURE;
}
+/*
+ * os_sendv_nonb - non blocking writev to a connection
+ * returns:
+ * 1 if data was written
+ * count_out contains amount written
+ *
+ * 0 if write call blocked, recoverable error
+ * -1 if an unrecoverable error occurred
+ */
+IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in,
+ unsigned int* count_out)
+{
+ int res;
+ int count;
+ struct iovec iov[IOV_MAX];
+
+ assert(0 != buf);
+ assert(0 != count_in);
+ assert(0 != count_out);
+
+ *count_in = 0;
+ *count_out = 0;
+ errno = 0;
+
+ count = msgq_mapiov(buf, iov, IOV_MAX, count_in);
+
+ if (-1 < (res = writev(fd, iov, count))) {
+ *count_out = (unsigned) res;
+ return IO_SUCCESS;
+ }
+ else if (EAGAIN == errno || ENOMEM == errno || ENOBUFS == errno)
+ return IO_BLOCKED;
+
+ return IO_FAILURE;
+}
+
int os_connect_nonb(int fd, const struct sockaddr_in* sin)
{
* $Id$
*
*/
+#define _XOPEN_SOURCE /* make limits.h #define IOV_MAX */
+
#include "ircd_osdep.h"
+#include "msgq.h"
#include <assert.h>
#include <errno.h>
+#include <limits.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <unistd.h>
/*
return IO_FAILURE;
}
+IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in,
+ unsigned int* count_out)
+{
+ int res;
+ int count;
+ struct iovec iov[IOV_MAX];
+
+ assert(0 != buf);
+ assert(0 != count_in);
+ assert(0 != count_out);
+
+ *count_in = 0;
+ *count_out = 0;
+ errno = 0;
+
+ count = msgq_mapiov(buf, iov, IOV_MAX, count_in);
+
+ if (-1 < (res = writev(fd, iov, count))) {
+ *count_out = (unsigned) res;
+ return IO_SUCCESS;
+ }
+ else if (EAGAIN == errno || ENOBUFS == errno ||
+ ENOMEM == errno || ENOSR == errno)
+ return IO_BLOCKED;
+
+ return IO_FAILURE;
+}
+
int os_connect_nonb(int fd, const struct sockaddr_in* sin)
{
if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) {
#include "list.h"
#include "listener.h"
#include "msg.h"
+#include "msgq.h"
#include "numeric.h"
#include "numnicks.h"
#include "packet.h"
* net.loads today anyway. Commented out the alarms to save cpu.
* --Run
*/
-unsigned int deliver_it(struct Client *cptr, const char *str, unsigned int len)
+unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf)
{
unsigned int bytes_written = 0;
+ unsigned int bytes_count = 0;
assert(0 != cptr);
- switch (os_send_nonb(cptr->fd, str, len, &bytes_written)) {
+ switch (os_sendv_nonb(cptr->fd, buf, &bytes_count, &bytes_written)) {
case IO_SUCCESS:
cptr->flags &= ~FLAGS_BLOCKED;
* XXX - hrmm.. set blocked here? the socket didn't
* say it was blocked
*/
- if (bytes_written < len)
+ if (bytes_written < bytes_count)
cptr->flags |= FLAGS_BLOCKED;
break;
case IO_BLOCKED:
#include "ircd_xopen.h"
#include "jupe.h"
#include "list.h"
-#include "msg.h"
#include "match.h"
+#include "msg.h"
+#include "msgq.h"
#include "numeric.h"
#include "numnicks.h"
#include "parse.h"
while (MsgQLength(&to->sendQ) > 0) {
unsigned int len;
- const char* msg = msgq_map(&to->sendQ, &len);
- if ((len = deliver_it(to, msg, len))) {
+ if ((len = deliver_it(to, &to->sendQ))) {
msgq_delete(&to->sendQ, len);
to->lastsq = MsgQLength(&to->sendQ) / 1024;
if (IsBlocked(to))