summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/m_spanningtree.cpp121
1 files changed, 87 insertions, 34 deletions
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index 4cc4b50d6..4cf8cbdea 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -27,12 +27,27 @@ using namespace std;
Server *Srv;
+// To attach sockets to the core of the ircd, we must use the InspSocket
+// class which can be found in socket.h. This class allows modules to create
+// listening and outbound sockets and attach sockets to existing (connected)
+// file descriptors. These file descriptors can then be associated with the
+// core of the ircd and bound to the socket engine.
+// To use InspSocket, we must inherit from it, as shown in TreeSocket below.
+
class TreeSocket : public InspSocket
{
std::string myhost;
public:
+ // InspSocket has several constructors used for various situations.
+ // This constructor is used to create a socket which may be used
+ // for both inbound and outbound (listen() and connect()) operations.
+ // When you inherit InspSocket you MUST call the superclass constructor
+ // within InspSocket, as shown below, unless you plan to completely
+ // override all behaviour of the class, which would prove to be more
+ // trouble than it's worth unless you're doing something really fancy.
+
TreeSocket(std::string host, int port, bool listening, unsigned long maxtime)
: InspSocket(host, port, listening, maxtime)
{
@@ -40,21 +55,33 @@ class TreeSocket : public InspSocket
myhost = host;
}
+ // This simpler constructor of InspSocket is used when you wish to
+ // associate an existing file descriptor with an InspSocket class,
+ // or a class inherited from InspSocket. As before, you must call
+ // the superclass. Not doing so will get your module into a whole
+ // world of hurt. Similarly, your inherited class MUST implement
+ // the constructors you use even if all it does is call the parent.
+
TreeSocket(int newfd)
: InspSocket(newfd)
{
- // Associate with an existing file descriptor (accepted from incoming connection)
}
+ // This method is called when an outbound socket (connect() style)
+ // finishes connecting. Connections are asyncronous, so you should
+ // not just assume that immediately after you instantiate a socket
+ // it is connected or failed. This takes time, and when the results
+ // are available for you, this method will be called.
+
virtual bool OnConnected()
{
- Srv->Log(DEBUG,"Connected");
- Srv->SendToModeMask("o",WM_AND,"*** CONNECTED!");
this->Write("GET / HTTP/1.1\r\nHost: " + myhost + "\r\nConnection: Close\r\n\r\n");
- Srv->SendToModeMask("o",WM_AND,"*** DATA WRITTEN ***");
- Srv->Log(DEBUG,"Wrote");
return true;
}
+
+ // When errors occur on the connection, this event will be triggered.
+ // Check the programmer docs for information on possible values for
+ // the InspSocketError type.
virtual void OnError(InspSocketError e)
{
@@ -64,16 +91,32 @@ class TreeSocket : public InspSocket
Srv->SendToModeMask("o",WM_AND,x);
}
+ // When a socket disconnects, this method is triggered. You cannot
+ // prevent the disconnection.
+
virtual int OnDisconnect()
{
Srv->Log(DEBUG,"Disconnect");
Srv->SendToModeMask("o",WM_AND,"*** DISCONNECTED!");
return true;
}
-
+
+ // When data is ready to be read from a socket, this method will
+ // be triggered, and within it, you should call this->Read() to
+ // read any pending data. Up to 10 kilobytes of data may be returned
+ // for each call to Read(), and you should not call Read() more
+ // than once per method call. You should also not call Read()
+ // outside of OnDataReady(), doing so will just result in Read()
+ // returning NULL. If Read() returns NULL and you are within the
+ // OnDataReady() event this usually indicates an EOF condition
+ // and the socket should be closed by returning false from this
+ // method. If you return false, the core will remove your socket
+ // from its list, and handle the cleanup (such as deleting the
+ // pointer) for you. This means you do not need to track your
+ // socket resources once they are associated with the core.
+
virtual bool OnDataReady()
{
- Srv->Log(DEBUG,"Data");
Srv->SendToModeMask("o",WM_AND,"*** DATA ***");
char* data = this->Read();
if (data)
@@ -82,41 +125,54 @@ class TreeSocket : public InspSocket
}
return (data != NULL);
}
+
+ // For outbound (connect style()) sockets only, the connection
+ // may time out, meaning that the time taken to connect was
+ // more than you specified when constructing the object.
+ // If this occurs, the OnTimeout method, as well as OnError,
+ // will be called to notify your class of the event.
virtual void OnTimeout()
{
- Srv->Log(DEBUG,"Timeout");
Srv->SendToModeMask("o",WM_AND,"*** TIMED OUT ***");
}
-
+
+ // For any type of socket, when the file descriptor is freed
+ // with close(), under any situation, the OnClose() method
+ // will be called.
+
virtual void OnClose()
{
Srv->SendToModeMask("o",WM_AND,"*** CLOSED ***");
}
+
+ // When a connection comes in over an inbound (listen() style)
+ // socket, the OnIncomingConnection method is triggered. You
+ // will be given a new file descriptor, and the ip of the
+ // connecting host. Most of the time, you will want to
+ // instantiate another class inherited from InspSocket,
+ // using the (int) constructor which will associate that class
+ // with the new file descriptor. You will usually then need
+ // to add that socket to the core, so that you will receive
+ // notifications for its activity.
virtual int OnIncomingConnection(int newsock, char* ip)
{
- Srv->SendToModeMask("o",WM_AND,"*** INCOMING ***");
- // use the (int) constructor to associate an incoming
- // connection with a class, without actually creating
- // a connection or binding from scratch.
TreeSocket* s = new TreeSocket(newsock);
Srv->AddSocket(s);
- char message[1024];
- sprintf(message,"Added new socket to list with fd %d from %s",newsock,ip);
- Srv->Log(DEBUG,message);
return true;
}
};
+// This is a test function which creates an outbound socket to a given
+// hostname. It provides an example of how to create a new outbound
+// socket to a host.
+
void handle_connecttest(char **parameters, int pcnt, userrec *user)
{
- // create a new class of type TreeSocket.
- std::string a = parameters[0];
- TreeSocket* s = new TreeSocket(a,80,false,10);
- Srv->Log(DEBUG,"Create TreeSocket");
- Srv->AddSocket(s);
- Srv->Log(DEBUG,"Added socket");
+ std::string addr = parameters[0];
+ TreeSocket* sock = new TreeSocket(addr,80,false,10);
+ Srv->AddSocket(sock);
}
class ModuleSpanningTree : public Module
@@ -125,30 +181,27 @@ class ModuleSpanningTree : public Module
ModuleSpanningTree()
{
Srv = new Server;
+
Srv->AddCommand("CONNECTTEST",handle_connecttest,'o',1,"m_spanningtree.so");
- Srv->Log(DEBUG,"ModCreate");
+
+ // This is an example of how to create a new inbound socket to a host.
+ // Please remember that so long as you AddSocket() your sockets, you
+ // do not need to track resources and do not need to delete your classes
+ // when you are finished with them.
+
TreeSocket* listeningsock = new TreeSocket("127.0.0.1",11111,true,10);
Srv->AddSocket(listeningsock);
}
-
- virtual void OnUserJoin(userrec* user, chanrec* channel)
- {
- }
-
+
virtual ~ModuleSpanningTree()
{
delete Srv;
}
-
+
virtual Version GetVersion()
{
return Version(1,0,0,0,VF_STATIC|VF_VENDOR);
}
-
- virtual void OnUserConnect(userrec* user)
- {
- }
-
};