/* -TAG:LICENSE-

   This file is under the DigitalSpark Freeware Class License, see the
   file LICENSE for complete licensing information.                    

                                                         -TAG:LICENSE- */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> 
#include <netdb.h>
#include <Strings.h>
#include <Threading.h>
#include "tricky.h"

#define SA struct sockaddr

extern	char	*NetGets( int sock );
extern	size_t 	Write( int slot, void *data, size_t size );
extern	void	SpoofServer( int Sock );
extern	void	IRCNotice( int Sock, char *type, char *message );
extern  void    ResumeIRCState( int Sock );
extern	void 	*ClientBridge( void );

/* thanks sno for the networking help :) */

void *Authorize( void )
{
char	*outbuff = 0;
char	*RealOutBuff = 0;
char    authphrase[1024];
char	*RealAuthPhrase = 0;
int	i=0,j=0;
int	ServerPass = 0;
pthread_attr_t attr, *attrPtr = &attr; 
pthread_t	ClientBridgePID;

pthread_attr_init(attrPtr);
pthread_attr_setdetachstate(attrPtr,1);

/* find a socket that needs to be accepted */
while ( i <= MAX_CLIENTS )
   {
   if ( Client[i].State == CS_WAITFOR )
      {
      if ( pthread_mutex_trylock(&Client[i].Mutex) == 0 )
         break;
      }
   i++;
   }

if ( i > MAX_CLIENTS )
   {
   Error(0,"Unnessisary connector spawned .. exiting.");
   pthread_exit(NULL);
   }

if ( Write(Client[i].Sock,"NOTICE AUTH :*** [TrickyIRC] Authorize, Now.\r\n",0) == -1 )
   {
   cBusRemove(Client[i].Sock);
   if ( ServerPass == 0 )
      pthread_mutex_unlock(&conbuff_mutex);
   pthread_exit(NULL);
   }

sprintf(authphrase,"PASS %s",GetConfigStr("Arbiter.AuthPhrase=",0));
RealAuthPhrase = StringToupper(authphrase);	// make it all capitals
ServerPass = pthread_mutex_trylock(&conbuff_mutex);

if (( ServerPass == 0 ) && ( ServerConnected == 0 ))
   ConBufSize=0;

while ( 1 )
   {
   // Get input from socket
   outbuff = NetGets(Client[i].Sock);
   // Check to make sure the socket is still there
   if ( outbuff == 0 )
      {
      Error(0,"Crack");
      cBusRemove(Client[i].Sock);
      if (( ServerConnected == 0 ) && ( ServerPass == 0 ))
         {
         while ( j < ConBufSize )
            {
            free(connectbuf[j]);
            j++;
            }
         ConBufSize = 0;
         pthread_mutex_unlock(&conbuff_mutex);
         }
      pthread_exit(NULL);
      }
   RealOutBuff = StringToupper(outbuff); // Make it all capitals
   //Error(0,outbuff);
   // The pass phrases match
   if ( strcmp(RealOutBuff,RealAuthPhrase) == 0 )
      break;

   if (( ServerConnected == 0 ) && ( ServerPass == 0 ))
      {
      connectbuf[ConBufSize] = malloc(strlen(outbuff)+1);
      strcpy(connectbuf[ConBufSize],outbuff);
      //Error(0,"CB[%i] = \"%s\"",ConBufSize,connectbuf[ConBufSize]);
      ConBufSize++;
      }
   // Clean up
   if ( RealOutBuff != 0 )
      free(RealOutBuff);
   if ( outbuff != 0 )
      free(outbuff);
   }

// Clean up
free(RealAuthPhrase);
if ( outbuff != 0 )
  free(outbuff);

if ( ServerPass == 0 )
   pthread_mutex_unlock(&conbuff_mutex);
Error(0,"Client(%i) authorized",i);

Client[i].Authorized = 1;
Client[i].State = CS_NEEDBRIDGE;

pthread_mutex_unlock(&Client[i].Mutex);

pthread_create(&ClientBridgePID, &attr, (void *)&ClientBridge, NULL);

while ( Client[i].State == CS_NEEDBRIDGE )
   usleep(EnforcedWait);

ClientConnected = 1;
Authorized = 1;
cBusBroadcast("NOTICE AUTH :*** [TrickyIRC] Client authorized\r\n",0);


if ( ServerConnected == 1 )
   {
   Error(0,"Client(%i) session resume",i);
   SpoofServer(Client[i].Sock);
   ResumeIRCState(Client[i].Sock);
   }

pthread_exit(NULL);
return 0;
}
