#include <pwd.h>
#include <grp.h>
+#include <sstream>
+
#include "socket_server.hxx"
#include "t2n_exception.hxx"
return;
}
+void socket_server::fill_connection_buffers()
+{
+ std::map<unsigned int, connection*>::iterator ie=connections.end();
+ for(std::map<unsigned int, connection*>::iterator i=connections.begin(); i != ie; i++)
+ if (!i->second->is_closed())
+ {
+ socket_connection* cp=dynamic_cast<socket_connection*>(i->second);
+ cp->fill_buffer(connection_set);
+ }
+}
+
socket_connection::socket_connection(int _sock, int _timeout)
: connection(_timeout)
{
}
-void socket_connection::fill_buffer(void)
+void socket_connection::fill_buffer(fd_set &cur_fdset)
{
+ bool try_again=false;
+
+ if (is_closed() || !FD_ISSET (sock, &cur_fdset))
+ return; // no data pending or connection closed
+
+ // data pending -> go and get it
+ char socket_buffer[recv_buffer_size];
+
+ int nbytes = read (sock, socket_buffer, recv_buffer_size);
+ if (nbytes < 0)
+ {
+ if (errno == EAGAIN)
+ {
+ if (my_server)
+ my_server->log(server::error,"read error: no data (EAGAIN) for connection "+get_id_string());
+ return;
+ }
+ else if (errno == EINTR)
+ {
+ // interrupted, try again
+ try_again=true;
+ }
+ else
+ {
+ if (my_server)
+ my_server->log(server::error,"error reading from socket of connection "+get_id_string()+": "+strerror(errno));
+ return;
+ }
+ }
+
+ // End-of-file
+ if (nbytes == 0 && !try_again)
+ {
+ close();
+ return;
+ }
+
+ // Data read -> store it
+ if (nbytes > 0)
+ buffer.assign(socket_buffer,nbytes);
+ // more data waiting?
+ fd_set active_fd_set;
+ struct timeval tval;
+
+ FD_ZERO (&active_fd_set);
+ FD_SET (sock, &active_fd_set);
+
+ /* no waiting */
+ tval.tv_sec=0;
+ tval.tv_usec=0;
+
+ if (select (FD_SETSIZE, &active_fd_set, NULL, NULL, &tval) >0)
+ {
+ /* more data waiting -> recurse */
+ fill_buffer(active_fd_set);
+ }
+
+ reset_timeout();
+
+ return;
}
void socket_connection::write(const std::string& data)
{
+ static const unsigned int write_block_size=4096;
+
+ if (is_closed())
+ return;
+
+ // prepend packet size to data
+ packet_size_indicator psize=data.size();
+ string send_data(data);
+ send_data.insert(0,(char*)psize,sizeof(packet_size_indicator));
+
+ int offset = 0;
+ while (offset < send_data.size())
+ {
+ unsigned int write_size=write_block_size;
+
+ if (offset+write_size > send_data.size())
+ write_size = send_data.size()-offset;
+ int rtn;
+ while ((rtn=::write(sock, send_data.data()+offset, write_size)) &&
+ rtn == -1 && (errno == EAGAIN || errno == EINTR))
+ {
+ usleep (80000);
+ if (my_server)
+ my_server->log(server::debug,"resuming write() call after EAGAIN or EINTR for connection "+get_id_string());
+ }
+
+ if (rtn == -1)
+ {
+ if (my_server)
+ my_server->log(server::error,"write() error on connection "+get_id_string()+": "+strerror(errno));
+ }
+ else if (rtn != write_size)
+ {
+ if (my_server)
+ {
+ ostringstream msg;
+ msg << "write() error on connection " << get_id()
+ << ": wrote " << rtn << " bytes, should have been "
+ << write_size << " (complete: " << send_data.size() << ")";
+
+ my_server->log(server::error,msg.str());
+ }
+ }
+
+ offset += write_size;
+ }
+
+ reset_timeout();
+
+ return;
}
}