MFEM v2.0
socketstream.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
00003 // reserved. See file COPYRIGHT for details.
00004 //
00005 // This file is part of the MFEM library. For more information and source code
00006 // availability see http://mfem.googlecode.com.
00007 //
00008 // MFEM is free software; you can redistribute it and/or modify it under the
00009 // terms of the GNU Lesser General Public License (as published by the Free
00010 // Software Foundation) version 2.1 dated February 1999.
00011 
00012 #include "socketstream.hpp"
00013 
00014 #include <cstring>      // memset, memcpy
00015 #include <netdb.h>      // gethostbyname
00016 #include <arpa/inet.h>  // htons
00017 #include <sys/types.h>  // socket, setsockopt, connect, recv, send
00018 #include <sys/socket.h> // socket, setsockopt, connect, recv, send
00019 #include <unistd.h>     // close
00020 
00021 int socketbuf::attach(int sd)
00022 {
00023    int old_sd = socket_descriptor;
00024    pubsync();
00025    socket_descriptor = sd;
00026    setg(NULL, NULL, NULL);
00027    setp(obuf, obuf + buflen);
00028    return old_sd;
00029 }
00030 
00031 int socketbuf::open(const char hostname[], int port)
00032 {
00033    struct sockaddr_in  sa;
00034    struct hostent     *hp;
00035 
00036    close();
00037    setg(NULL, NULL, NULL);
00038    setp(obuf, obuf + buflen);
00039 
00040    hp = gethostbyname(hostname);
00041    if (hp == NULL)
00042    {
00043       socket_descriptor = -3;
00044       return -1;
00045    }
00046    memset(&sa, 0, sizeof(sa));
00047    memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length);
00048    sa.sin_family = hp->h_addrtype;
00049    sa.sin_port = htons(port);
00050    socket_descriptor = socket(hp->h_addrtype, SOCK_STREAM, 0);
00051    if (socket_descriptor < 0)
00052       return -1;
00053    if (connect(socket_descriptor,
00054                (const struct sockaddr *)&sa, sizeof(sa)) < 0)
00055    {
00056       ::close(socket_descriptor);
00057       socket_descriptor = -2;
00058       return -1;
00059    }
00060    return 0;
00061 }
00062 
00063 int socketbuf::close()
00064 {
00065    if (is_open())
00066    {
00067       pubsync();
00068       int err = ::close(socket_descriptor);
00069       socket_descriptor = -1;
00070       return err;
00071    }
00072    return 0;
00073 }
00074 
00075 int socketbuf::sync()
00076 {
00077    ssize_t bw, n = pptr() - pbase();
00078    // std::cout << "[socketbuf::sync n=" << n << ']' << std::endl;
00079    while (n > 0)
00080    {
00081 #ifdef MSG_NOSIGNAL
00082       bw = send(socket_descriptor, pptr() - n, n, MSG_NOSIGNAL);
00083 #else
00084       bw = send(socket_descriptor, pptr() - n, n, 0);
00085 #endif
00086       if (bw < 0)
00087       {
00088          setp(pptr() - n, obuf + buflen);
00089          pbump(n);
00090          return -1;
00091       }
00092       n -= bw;
00093    }
00094    setp(obuf, obuf + buflen);
00095    return 0;
00096 }
00097 
00098 socketbuf::int_type socketbuf::underflow()
00099 {
00100    // assuming (gptr() < egptr()) is false
00101    ssize_t br = recv(socket_descriptor, ibuf, buflen, 0);
00102    // std::cout << "[socketbuf::underflow br=" << br << ']'
00103    //           << std::endl;
00104    if (br <= 0)
00105    {
00106       setg(NULL, NULL, NULL);
00107       return traits_type::eof();
00108    }
00109    setg(ibuf, ibuf, ibuf + br);
00110    return traits_type::to_int_type(*ibuf);
00111 }
00112 
00113 socketbuf::int_type socketbuf::overflow(int_type c)
00114 {
00115    if (sync() < 0)
00116       return traits_type::eof();
00117    if (traits_type::eq_int_type(c, traits_type::eof()))
00118       return traits_type::not_eof(c);
00119    *pptr() = traits_type::to_char_type(c);
00120    pbump(1);
00121    return c;
00122 }
00123 
00124 std::streamsize socketbuf::xsgetn(char_type *__s, std::streamsize __n)
00125 {
00126    // std::cout << "[socketbuf::xsgetn __n=" << __n << ']'
00127    //           << std::endl;
00128    const std::streamsize bn = egptr() - gptr();
00129    if (__n <= bn)
00130    {
00131       traits_type::copy(__s, gptr(), __n);
00132       gbump(__n);
00133       return __n;
00134    }
00135    traits_type::copy(__s, gptr(), bn);
00136    setg(NULL, NULL, NULL);
00137    std::streamsize remain = __n - bn;
00138    char_type *end = __s + __n;
00139    ssize_t br;
00140    while (remain > 0)
00141    {
00142       br = recv(socket_descriptor, end - remain, remain, 0);
00143       if (br <= 0)
00144          return (__n - remain);
00145       remain -= br;
00146    }
00147    return __n;
00148 }
00149 
00150 std::streamsize socketbuf::xsputn(const char_type *__s, std::streamsize __n)
00151 {
00152    // std::cout << "[socketbuf::xsputn __n=" << __n << ']'
00153    //           << std::endl;
00154    if (pptr() + __n <= epptr())
00155    {
00156       traits_type::copy(pptr(), __s, __n);
00157       pbump(__n);
00158       return __n;
00159    }
00160    if (sync() < 0)
00161       return 0;
00162    ssize_t bw;
00163    std::streamsize remain = __n;
00164    const char_type *end = __s + __n;
00165    while (remain > buflen)
00166    {
00167 #ifdef MSG_NOSIGNAL
00168       bw = send(socket_descriptor, end - remain, remain, MSG_NOSIGNAL);
00169 #else
00170       bw = send(socket_descriptor, end - remain, remain, 0);
00171 #endif
00172       if (bw < 0)
00173          return (__n - remain);
00174       remain -= bw;
00175    }
00176    if (remain > 0)
00177    {
00178       traits_type::copy(pptr(), end - remain, remain);
00179       pbump(remain);
00180    }
00181    return __n;
00182 }
00183 
00184 
00185 socketserver::socketserver(int port)
00186 {
00187    listen_socket = socket(PF_INET, SOCK_STREAM, 0); // tcp socket
00188    if (listen_socket < 0)
00189    {
00190       return;
00191    }
00192    int on = 1;
00193    if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
00194                   &on, sizeof(on)) < 0)
00195    {
00196       ::close(listen_socket);
00197       listen_socket = -2;
00198       return;
00199    }
00200    struct sockaddr_in sa;
00201    memset(&sa, 0, sizeof(sa));
00202    sa.sin_family = AF_INET;
00203    sa.sin_port = htons(port);
00204    sa.sin_addr.s_addr = INADDR_ANY;
00205    if (bind(listen_socket, (const struct sockaddr *)&sa, sizeof(sa)))
00206    {
00207       ::close(listen_socket);
00208       listen_socket = -3;
00209       return;
00210    }
00211    const int backlog = 4;
00212    if (listen(listen_socket, backlog) < 0)
00213    {
00214       ::close(listen_socket);
00215       listen_socket = -4;
00216       return;
00217    }
00218 }
00219 
00220 int socketserver::close()
00221 {
00222    if (!good())
00223       return 0;
00224    int err = ::close(listen_socket);
00225    listen_socket = -1;
00226    return err;
00227 }
00228 
00229 int socketserver::accept(socketstream &sockstr)
00230 {
00231    if (!good())
00232       return -1;
00233    int socketd = ::accept(listen_socket, NULL, NULL);
00234    if (socketd >= 0)
00235    {
00236       sockstr.rdbuf()->close();
00237       sockstr.rdbuf()->attach(socketd);
00238    }
00239    return socketd;
00240 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines