socket.cc revision 5523
17199Sgblack@eecs.umich.edu/*
27199Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
37199Sgblack@eecs.umich.edu * All rights reserved.
47199Sgblack@eecs.umich.edu *
57199Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67199Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77199Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87199Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97199Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107199Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117199Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127199Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137199Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147199Sgblack@eecs.umich.edu * this software without specific prior written permission.
157199Sgblack@eecs.umich.edu *
167199Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177199Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187199Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197199Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207199Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217199Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227199Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237199Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247199Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257199Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267199Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277199Sgblack@eecs.umich.edu *
287199Sgblack@eecs.umich.edu * Authors: Nathan Binkert
297199Sgblack@eecs.umich.edu */
307199Sgblack@eecs.umich.edu
317199Sgblack@eecs.umich.edu#include <sys/types.h>
327199Sgblack@eecs.umich.edu#include <sys/socket.h>
337199Sgblack@eecs.umich.edu
347199Sgblack@eecs.umich.edu#include <netinet/in.h>
357199Sgblack@eecs.umich.edu#include <netinet/tcp.h>
367199Sgblack@eecs.umich.edu
377199Sgblack@eecs.umich.edu#include <errno.h>
387199Sgblack@eecs.umich.edu#include <unistd.h>
397199Sgblack@eecs.umich.edu
407199Sgblack@eecs.umich.edu#include "sim/host.hh"
417199Sgblack@eecs.umich.edu#include "base/misc.hh"
427199Sgblack@eecs.umich.edu#include "base/socket.hh"
437199Sgblack@eecs.umich.edu
447199Sgblack@eecs.umich.eduusing namespace std;
457199Sgblack@eecs.umich.edu
467199Sgblack@eecs.umich.edubool ListenSocket::listeningDisabled = false;
477199Sgblack@eecs.umich.edubool ListenSocket::anyListening = false;
487199Sgblack@eecs.umich.edu
497199Sgblack@eecs.umich.eduvoid
507199Sgblack@eecs.umich.eduListenSocket::disableAll()
517199Sgblack@eecs.umich.edu{
527199Sgblack@eecs.umich.edu    if (anyListening)
537199Sgblack@eecs.umich.edu        panic("Too late to disable all listeners, already have a listener");
547199Sgblack@eecs.umich.edu    listeningDisabled = true;
557199Sgblack@eecs.umich.edu}
567199Sgblack@eecs.umich.edu
577199Sgblack@eecs.umich.edubool
587202Sgblack@eecs.umich.eduListenSocket::allDisabled()
597202Sgblack@eecs.umich.edu{
607202Sgblack@eecs.umich.edu    return listeningDisabled;
617202Sgblack@eecs.umich.edu}
627202Sgblack@eecs.umich.edu
637202Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////////
647202Sgblack@eecs.umich.edu//
657202Sgblack@eecs.umich.edu//
667599Sminkyu.jeong@arm.com
677783SGiacomo.Gabrielli@arm.comListenSocket::ListenSocket()
687202Sgblack@eecs.umich.edu    : listening(false), fd(-1)
697202Sgblack@eecs.umich.edu{}
707202Sgblack@eecs.umich.edu
717202Sgblack@eecs.umich.eduListenSocket::~ListenSocket()
727202Sgblack@eecs.umich.edu{
737202Sgblack@eecs.umich.edu    if (fd != -1)
747202Sgblack@eecs.umich.edu        close(fd);
757599Sminkyu.jeong@arm.com}
767783SGiacomo.Gabrielli@arm.com
777202Sgblack@eecs.umich.edu// Create a socket and configure it for listening
787202Sgblack@eecs.umich.edubool
797202Sgblack@eecs.umich.eduListenSocket::listen(int port, bool reuse)
807202Sgblack@eecs.umich.edu{
817202Sgblack@eecs.umich.edu    if (listening)
827400SAli.Saidi@ARM.com        panic("Socket already listening!");
837202Sgblack@eecs.umich.edu
847400SAli.Saidi@ARM.com    fd = ::socket(PF_INET, SOCK_STREAM, 0);
857202Sgblack@eecs.umich.edu    if (fd < 0)
867797Sgblack@eecs.umich.edu        panic("Can't create socket:%s !", strerror(errno));
877797Sgblack@eecs.umich.edu
887202Sgblack@eecs.umich.edu    if (reuse) {
897202Sgblack@eecs.umich.edu        int i = 1;
907202Sgblack@eecs.umich.edu        if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i,
917202Sgblack@eecs.umich.edu                         sizeof(i)) < 0)
927599Sminkyu.jeong@arm.com            panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!");
937599Sminkyu.jeong@arm.com    }
947202Sgblack@eecs.umich.edu
957202Sgblack@eecs.umich.edu    struct sockaddr_in sockaddr;
967202Sgblack@eecs.umich.edu    sockaddr.sin_family = PF_INET;
977202Sgblack@eecs.umich.edu    sockaddr.sin_addr.s_addr = INADDR_ANY;
987202Sgblack@eecs.umich.edu
997202Sgblack@eecs.umich.edu    sockaddr.sin_port = htons(port);
1007202Sgblack@eecs.umich.edu    int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr));
1017599Sminkyu.jeong@arm.com    if (ret != 0) {
1027599Sminkyu.jeong@arm.com        if (ret == -1 && errno != EADDRINUSE)
1037202Sgblack@eecs.umich.edu            panic("ListenSocket(listen): bind() failed!");
1047202Sgblack@eecs.umich.edu        return false;
1057202Sgblack@eecs.umich.edu    }
1067202Sgblack@eecs.umich.edu
1077202Sgblack@eecs.umich.edu    if (::listen(fd, 1) == -1)
1087400SAli.Saidi@ARM.com        panic("ListenSocket(listen): listen() failed!");
1097202Sgblack@eecs.umich.edu
1107400SAli.Saidi@ARM.com    listening = true;
1117202Sgblack@eecs.umich.edu
1127797Sgblack@eecs.umich.edu    anyListening = true;
1137797Sgblack@eecs.umich.edu    return true;
1147202Sgblack@eecs.umich.edu}
1157202Sgblack@eecs.umich.edu
1167202Sgblack@eecs.umich.edu
1177202Sgblack@eecs.umich.edu// Open a connection.  Accept will block, so if you don't want it to,
1187599Sminkyu.jeong@arm.com// make sure a connection is ready before you call accept.
1197599Sminkyu.jeong@arm.comint
1207202Sgblack@eecs.umich.eduListenSocket::accept(bool nodelay)
1217202Sgblack@eecs.umich.edu{
1227202Sgblack@eecs.umich.edu    struct sockaddr_in sockaddr;
1237202Sgblack@eecs.umich.edu    socklen_t slen = sizeof (sockaddr);
1247202Sgblack@eecs.umich.edu    int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen);
1257202Sgblack@eecs.umich.edu    if (sfd != -1 && nodelay) {
1267202Sgblack@eecs.umich.edu        int i = 1;
1277599Sminkyu.jeong@arm.com        ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i));
1287599Sminkyu.jeong@arm.com    }
1297202Sgblack@eecs.umich.edu
1307202Sgblack@eecs.umich.edu    return sfd;
1317202Sgblack@eecs.umich.edu}
1327209Sgblack@eecs.umich.edu