source: trunk/MagicSoft/Control/SubsystemIO/TCPListener.ionotifier.C@ 1041

Last change on this file since 1041 was 1041, checked in by casaldaliga, 23 years ago
First release
File size: 5.0 KB
Line 
1/* Copyright (C) 2001 Marc Casaldaliga Albisu <casaldaliga@ifae.es>
2================================================================
3
4 This code is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This code is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Emacs (which is required to make this stuff work); if
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.
18==================================================================
19*/
20
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24#include "socket_functions.h"
25#include "IONotifier.H"
26#include "TCPListener.H"
27#include <string>
28//for signals/slots (Callbacks in C++, see http://libsigc.sourceforge.net/
29#include <sigc++/signal_system.h>
30using namespace SigC;
31//for perror
32#include <stdio.h>
33//for close
34#include <unistd.h>
35
36
37TCPListener::TCPListener (int port_)
38 :port(port_),newReceived(false),comMode(false),notifierOfIncomingConn(0),channelReadable(0)
39{
40 socketItself=make_socket(port);
41 //specify that socketItself it's willing to listen only at one client at a time
42
43 if( listen(socketItself,1)<0){
44 perror("in listen");
45 }
46 notifierOfIncomingConn=new IONotifier(socketItself);
47 //when notifierOfIncomingConn becomes readable it's because it is recieving an incoming connection, Accept it with accept method. The next statment connects this readable signal to accept slot
48 notifierOfIncomingConn->readable.connect(slot(*this,&TCPListener::Accept));
49
50}
51
52TCPListener::~TCPListener() {
53 if(comMode){
54 cerr<<"deleting\n";
55
56 this->ClosingChannel();
57 }
58 delete notifierOfIncomingConn;
59 close(socketItself);
60}
61
62void TCPListener::Accept () {
63 size_t size=sizeof(socketAddr);
64 channel=accept(socketItself, (struct sockaddr *) &socketAddr, &size);
65 if(channel<0){
66 perror("in Accept");
67// exit (EXIT_FAILURE);
68 }else{
69//first of all, don't acccept new connections
70 delete notifierOfIncomingConn;
71
72 clientAddress=inet_ntoa(socketAddr.sin_addr);
73 clientPort=ntohs(socketAddr.sin_port);
74 fprintf(stderr, "TCPListener: client contacted from %s:%hd\n", clientAddress, clientPort);
75// fconfigure $channel -buffering line
76// assume channel opens a O_SYNC
77 channelReadable=new IONotifier(channel);
78 channelReadable->readable.connect(slot(this,&TCPListener::Receive));
79 comMode=true;
80
81 }
82}
83
84
85//this next method is only internally called when something arrives at channel (be careful, it can be the connection has closed)
86void TCPListener::Receive () { //Syncronous receive. If you are not sure there will be data to read, schedule this receive with IONotifier or something. Otherwise it will block
87// cerr << "Receive\n"
88 int nbytes;
89 nbytes = read (channel, receivedStream, MAXMSG);
90 if (nbytes < 0){
91 /* Read error. */
92 perror("TCPListener: read");
93 exit (EXIT_FAILURE);
94 }else if (nbytes == 0){
95
96 /* End-of-file. */
97 receivedStream[0]='0';
98 receivedStream[1]='\0';
99 this->ClosingChannel();
100 }else{
101 /* Data read. */
102 //look for '\n' and chomp, in anycase read doesn't supply the \n so add it
103 if(receivedStream[nbytes-1]=='\n'){
104 receivedStream[nbytes-1]='\0';
105#ifdef DEBUG
106 printf("TCPListener: chomp\n");
107#endif
108 }else{
109 receivedStream[nbytes]='\0';
110 }
111#ifdef DEBUG
112 printf("TCPListener: got message: `%s'\n", receivedStream);
113#endif
114 this->process();
115 newReceived=true;
116 }
117}
118
119void TCPListener::ClosingChannel(){
120 cerr<<"TCPListener: closing socket to client from "<<clientAddress<<":"<<clientPort<<"\n";
121 delete channelReadable;
122 close(channel);
123 comMode=false;
124//setup again
125 notifierOfIncomingConn=new IONotifier(socketItself);
126 //when notifierOfIncomingConn becomes readable it's because it is recieving an incoming connection, Accept it with accept method. The next statment connects this readable signal to accept slot
127 notifierOfIncomingConn->readable.connect(slot(*this,&TCPListener::Accept));
128
129}
130//this public method should be capitalized for some consistency. Put the change should be propagated. class Make up!
131void TCPListener::process (){
132//to be overriden
133 cerr<<"TCPListener: message Received ["<<receivedStream<<"] and processed from "<<clientAddress<<":"<<clientPort<<"\n";
134
135}
136
137string TCPListener::ReturnNew () {
138 if (newReceived) {
139 newReceived=false;
140 return string(receivedStream);
141 }else{
142 return string("0");
143 }
144}
145
146
Note: See TracBrowser for help on using the repository browser.