Peercast core Code Execution Process

Source: Internet
Author: User

The execution process is roughly as follows:
Create a servmgr object when peercast is started
Servmgr starts two server threads: servproc and idleproc.
Servproc starts two listening servents for listening to ports 7144 and 7145 respectively.
Listener servent start server listening thread servent: servproc
When the server listening thread detects a new connection, it allocates a new servent to the connection.
New servent initializes connection information and starts the incomingproc thread
The incomingproc thread calls handshakeincoming for processing.
Handshakeincoming reads the sent request. If it is an HTTP request, handshakehttp is called for processing.
Handshakehttp processes HTTP requests and replies accordingly. handshakepls is called for processing if it is a channel request, and handshakecmd is called for processing if it is a control request (Admin request, if it is a playback request, triggerchannel is called for corresponding processing (for details, see the analysis of the playback module)

Windows programs start from winmain.
Int apientry winmain ()
{
Peercastinst = new mypeercastinst ();
Peercastapp = new mypeercastapp ();

Peercastinst-> Init ();
}

// Initialize the entire program, create sys, servmgr, and chanmgr objects, and read information from the configuration file
// Sys, servmgr, and chanmgr are the three most important global variables in the system, supporting most of the operations of peercast core code.
// Sys is used to provide underlying operations, such as creating a socket and obtaining the system time. It can be understood as an object that implements the class of the system library.
// Servmgr is used to manage network transmission and implement functions such as listening, sending and receiving information. chanmgr is used to manage channels.
Void apicall peercastinstance: Init ()
{
Sys = createsys ();
Servmgr = new servmgr ();
Chanmgr = new chanmgr ();

// Read the configuration information in the configuration file
If (peercastapp-> getinifilename ())
Servmgr-> loadsettings (peercastapp-> getinifilename ());

Servmgr-> Start ();
}

// Servmgr starts two threads, of which serverproc listens to port 7144, processes incoming connections and sends data
// Idleproc operates in the idle time of the program, such as sending information to YP.
Bool servmgr: Start ()
{
Serverthread. func = servmgr: serverproc;
If (! Sys-> startthread (& serverthread ))
Return false;

Idlethread. func = servmgr: idleproc;
If (! Sys-> startthread (& idlethread ))
Return false;

Return true;
}

// Let's take a look at the execution of the server thread.
//--------------------------------------------------
// Start the server process, allocate two servents, and initialize sock. By default, serv listens to port 7144 and serv2 listens to port 7145.
Int servmgr: serverproc (threadinfo * thread)
{
Servent * serv = servmgr-> allocservent ();
Servent * serv2 = servmgr-> allocservent ();

While (thread-> active)
{
If (servmgr-> autoserve)
{
If ((! Serv-> sock) | (! Serv2-> sock ))
{
Log_debug ("Starting servers ");
{
Host H = servmgr-> serverhost;

If (! Serv-> sock)
Serv-> initserver (h );

H. Port ++;
If (! Serv2-> sock)
Serv2-> initserver (h );
}
}
} Else {
// Stop Server
Serv-> abort (); // force close
Serv2-> abort (); // force close

// Cancel incoming connectuions
Servent * s = servmgr-> servents;
While (s)
{
If (S-> type = servent: t_incoming)
S-> thread. Active = false;
S = s-> next;
}

Servmgr-> setfirewall (servmgr: fw_on );
}

Sys-> sleepidle ();

}

Sys-> endthread (thread );

Return 0;
}

// Start a listening thread for each listener's servent
// Start the serverproc thread for server listening
Bool servent: initserver (host & H)
{
Createsocket ();
Sock-> BIND (h );
Thread. Data = this;
Thread. func = serverproc;
Type = t_server;
If (! Sys-> startthread (& Thread ))
Throw streamexception ("can't start thread ");

Return true;
}

// Let's see how the server listening thread runs.
Int servent: serverproc (threadinfo * thread)
{
Servent * SV = (servent *) thread-> data;

Try
{
If (! SV-> sock)
Throw streamexception ("server has no socket ");

SV-> setstatus (s_listening); // you can specify the listener status.

Char servip [64];
SV-> sock-> host. tostr (servip); // servip is "127.0.0.1: 7144"

While (thread-> active) & (SV-> sock-> active ()))
{
If (servmgr-> numactiveonport (SV-> sock-> host. Port) <servmgr-> maxservin)
{
Clientsocket * cs = SV-> sock-> Accept (); // create a new socket to accept the connection
// Cyclically determine the value of CS. If CS is not empty, a new connection is established.
// This is a non-blocking method to determine whether a new connection exists.
If (CS)
{
Log_debug ("accepted incoming ");
Servent * NS = servmgr-> allocservent (); // create a servent ns to process connection requests
If (NS)
{
Servmgr-> lastincoming = sys-> gettime ();
NS-> servport = SV-> sock-> host. port;
NS-> networkid = servmgr-> networkid;
NS-> initincoming (CS, SV-> allow); // use initincoming to process the sent information
} Else
Log_error ("out of servents ");
}
}
Sys-& gt; sleep (100 );
}
} Catch (streamexception & E)
{
Log_error ("server error: % s: % d", E. MSG, E. Err );
}

 
Log_debug ("server stopped ");

SV-> kill ();
Sys-> endthread (thread );
Return 0;
}

// When the listening server thread detects a new connection, it allocates a new servent, initializes incoming, and starts the thread to call incomingproc for incoming processing.
Void servent: initincoming (clientsocket * s, unsigned int)
{

Try {

Checkfree ();

Type = t_incoming;
Sock = s;
Allow =;
Thread. Data = this;
Thread. func = incomingproc;

Setstatus (s_protocol );

Char ipstr [64];
Sock-> host. tostr (ipstr );
Log_debug ("Incoming from % s", ipstr );

If (! Sys-> startthread (& Thread ))
Throw streamexception ("can't start thread ");
} Catch (streamexception & E)
{
// Log_error ("!! Fatal !! Incoming error: % s ", E. msg );
// Servmgr-> shutdowntimer = 1;
Kill ();

Log_error ("Incoming failed: % s", E. msg );

}
}

// Call handshakeincoming for incoming Processing
Int servent: incomingproc (threadinfo * thread)
{
// Thread-> lock ();

Servent * SV = (servent *) thread-> data;
 
Char ipstr [64];
SV-> sock-> host. tostr (ipstr );

Try
{
SV-> handshakeincoming ();
} Catch (httpexception & E)
{
Try
{
SV-> sock-> writeline (E. msg );
If (E. Code = 401)
SV-> sock-> writeline ("www-Authenticate: Basic realm =/" peercast /"");
SV-> sock-> writeline ("");
} Catch (streamexception &){}
Log_error ("Incoming from % s: % s", ipstr, E. msg );
} Catch (streamexception & E)
{
Log_error ("Incoming from % s: % s", ipstr, E. msg );
}

SV-> kill ();
Sys-> endthread (thread );
Return 0;
}

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.