/*     
        SCOL FRONTEND . 1997 . Sylvain HUET

         mainscol.h : gestion des evenements
*/
// Modification history:
//$ FA(03/05/2001): Commented out #include "analyzer.h" (not used)
//$ FA(21/05/2001): Debugger integration. Filter READs.
//$ FA(01/06/2001): Comment MMpull() after call to SCexeccomm()
//$ FA(06/06/2001): Includes baselib.h
//$ FA(18/06/2001): Debugger integration. Filter WRITEs.
//$ FA(12/11/2001): Replace SCOL_DEBUGGER_AWARE by INCLUDE_DEBUGGER
//

#include "scolPrerequisites.h"

#include <stdio.h>
#include <string.h>

#include "common/vscol.h"
#if SCOL_PLATFORM == SCOL_PLATFORM_WINDOWS
#  include <winsock.h>
#endif

#include "common/common.h"

#include "scolMMemory.h"
#include "vm/mbytec.h"
#include "baselib.h"
#include "listlab.h"
#include "loadpak.h"
#include "scol.h"
#include "scolSystem.h"
#include "scolsign.h"
#include "scolpack.h"
#include "fifo.h"
#include "common/socket.h"
#include "common/cpu_detect.h"
#include "scolobj.h"
#include "debug.h"

/***************************************************
 Very important: this is the scol machine instance!
***************************************************/
struct Mmachine mscol;

char scriptname[1024];
char scriptcontent[1024];
char userscript[1024*16];
int ScolMemoryLength = 0;
int firstScol = SCOL_INSTANCE_NORMAL;
char autoHTTPproxy[256];
char autoSOCKSproxy[256];
char HTTPproxy[256];


int SCOLInit()
{
#ifdef OPTI_P3
	if(testP3())		{	infoP3 = 1;	MMechostr(0,"*****  SSE1 supported !                                       *****\n" ); }
	else						{	infoP3 = 0;	MMechostr(0,"*****  SSE1 not supported                                     *****\n" ); }
#endif

#ifdef OPTI_P4
	if(testP4())		{	infoP4 = 1;	MMechostr(0,"*****  SSE2 supported !                                       *****\n" ); }
	else						{	infoP4 = 0;	MMechostr(0,"*****  SSE2 not supported                                     *****\n" ); }
#endif

	return 0;
}


int SCOLNetEvent(mmachine mscol, int hSock, int NetEvent, int NetError)
{
  //$BLG - v5.22: Modif
  //char buf[1024];
  char buf[65536];
  
  int len;
  int k;
  int ip, port;
  
  //$BLG - v5.22: Add
  int i;
  int ret;

  k = 0;
  if (NetError) {
      //$ FA(06/08/2001): Add the error code into the message
      MMechostr(MSKWARNING, "Error #%d on socket #%d\n", NetError, hSock);
      if (SCselectcanal(mscol, hSock) == 0)
          SCchanneldown(mscol);
      k = -1;
  } 
  else
    switch(NetEvent)
    {
      case FD_ACCEPT :
        MMechostr(MSKDEBUG, "ACCEPT %d\n", hSock);
        if (SCgetserver(mscol, hSock)) break;
        SCaccept(mscol, hSock);
        MMechostr(MSKDEBUG, "ACCEPT_OK\n");
        break;
      case FD_READ :
//$ FA(07/12/2000): Filter debugging server messages
#if defined(INCLUDE_DEBUGGER)
        if (hSock == debug.sock) 
        {
		      // Virtual machine should be closed here if needed
          if (DBGServiceDebugger(mscol) == MERRCLOSE)
		        SCclosemachine(mscol);
		      break;
        }
#endif
//
        MMechostr(MSKDEBUG, "READ %d\n", hSock);
        //$BLG - v5.22: Modif
        //len = SCKrecv(hSock, buf, 1024, &ip, &port);
        len = SCKrecv(hSock, buf, 65536, &ip, &port);
        if (len < 0)
        {
          if (SCselectcanal(mscol, hSock)) break;
          SCchanneldown(mscol);
          k = -1;
          MMechostr(MSKWARNING, "READ_CLOSE\n");
          break;
        }
        
        //$BLG - v5.22: Add
        MMechostr(0, ">CHK BUF:\n");
        for (i = 0; i < len; i++)
        {
        	if (buf[i] == 0)	MMechostr(0, "%d: 0\n", i);
        }
        
        if (SCselectcanal(mscol, hSock)) break;
        MMechostr(MSKDEBUG, ">SCread %d\n", len);
        
	    	//$BLG - v5.22: Modif
	    	//SCread(mscol, buf, len, ip, port);
	    	ret = SCread(mscol, buf, len, ip, port);
        
        MMechostr(MSKDEBUG, "<SCread\n");
        
        //$BLG - v5.22: Modif
        //MMechostr(MSKDEBUG, "READ_OK\n");
        if (ret == 0)
        	MMechostr(MSKDEBUG, "READ_OK\n");
        else
        	MMechostr(MSKDEBUG, "READ_NOT_OK\n");
        
        break;
      case FD_WRITE :
//$ FA(19/06/2001): Filter debugging server messages
#if defined(INCLUDE_DEBUGGER)
        if (hSock == debug.sock)
          break;
#endif
//
        MMechostr(MSKDEBUG, "WRITE %d\n", hSock);
        if (SCselectcanal(mscol, hSock)) break;
        if (SCwrite(mscol) == 1)
	  		{
          SCchanneldown(mscol);
          k = -1;
          MMechostr(MSKWARNING, "WRITE_CLOSE\n");
          break;
        }
        MMechostr(MSKDEBUG, "WRITE_OK\n");
        break;
      case FD_CLOSE :
        MMechostr(MSKDEBUG, "CLOSE %d\n", hSock);
        k = -1;
        if (SCselectcanal(mscol, hSock)) break;
        //$BLG - v5.22: Modif
        //len = SCKrecv(hSock, buf, 1024, &ip, &port);
        len = SCKrecv(hSock, buf, 65536, &ip, &port);
        if (len > 0) SCread(mscol, buf, len, ip, port);
        SCchanneldown(mscol);
        break;
      default:
        break;
      }        
  
  return k;
}


extern int activeChannel;


int SCOLsend(mmachine m, char *buf)
{
	int k;
MMechostr(MSKDEBUG,"receive message : %s\n",buf);
  
  MMpush(m,MMgetglobal(m,OFFSCCUR));
	if (SCselectcanal(m,activeChannel)) return 0;
  if (k=SCexeccomm(m,buf)) return 0;
//    MMpull(m);
	MMsetglobal(m,OFFSCCUR,MMpull(m));
	return 0;
}

int StartQuotaThread (char *path,int size);


extern int fstart;


int tstscoldead(int i)
{
	int k;

	if (fstart != 1) return 0;

    if (k = SCisdead(&mscol))
    {
      MMechostr(MSKRUNTIME, "Dead Scol Machine %d (%d)\n", k, i);
			Mprinterror(k);
			if ((k<0)&&(k!=MERRCLOSE))
			{
	//			_asm { int 3};
				EndScolMachine(-1);
			}
	    else 
	    	EndScolMachine(0);
    }
    return 0;
}


char *ScolGetName(char *name)
{
  int i, k;

  i = k = 0;
  while(name[i])
  {
    if ((name[i] == '\\') || (name[i] == '/')) 	k = i + 1;
    i++;
  }
	return &name[k];
}


int ScolGetPath(char *path, char *name)
{
  int i, k;

  k = 0;
  i = 0;
  while(name[i])
  {
    if ((name[i] == '\\') || (name[i] == '/')) 	k = i;
    i++;
  }
  strcpy(path, name);
  path[k] = 0;
  return 0;
}

int mainscol()
{
  char script[1024*15];
  int n;
  FILE *f;
  char *p;
	
	//$BLG - v5.21: Add
	MMechostr(MSKTRACE,"\n> Scol configuration\n");
	
	ScolMemoryLength = 1024 * 256;
  //$BLG - v5.11: Modif
  //MMechostr(MSKTRACE,"initialisation: %d\n",ScolMemoryLength);
  //$BLG note: Remember the memory is defined as the number of 32bits chunks that will be allocated
  MMechostr(MSKTRACE, "Starting memory allocation : %d MB\n", ScolMemoryLength / (1024 * 256));
	//if (!ScolMemoryLength) ScolMemoryLength=1024*1024;
  if (SCinit(&mscol, ScolMemoryLength)) return -1;

	//MMechostr(0, "DBG\n%s\n%s\n<\n", scriptname, scriptcontent);
	if (scriptname[0] == 0)
	{
		ScolSuper = 1;
		strcpy(scriptname, "scol.scol");
		strcpy(scriptcontent, "$");
		script[0] = '\0';
		userscript[0] = '\0';
#if SCOL_PLATFORM == SCOL_PLATFORM_WINDOWS
		if (Cachepack) StartQuotaThread(Cachepack->path, Cachepack->quota);
#endif
		strcpy(script, "_load \"locked/lib/stdlib.pkg\"\n");
		strcat(script, "_load \"locked/lib/loc.pkg\"\n");
		strcat(script, "_load \"locked/lib/treeedit.pkg\"\n");
		strcat(script, "_load \"locked/lib/textedit.pkg\"\n");
		strcat(script, "_load \"locked/master.pkg\"\n");
		sprintf(script, "%smain %x\n", script, STDPORT);
	}
  else
	{
		if (scriptcontent[0] == '$')
		{
			sprintf(script, "_load \"locked/slv.pkg\"\nmain \":%d\" \"%s\"", STDPORT, ScolGetName(scriptname));
			//$BLG - v5.11: Modif
			//MMechostr(MSKTRACE,"ouverture script %s\n",scriptname);
			MMechostr(MSKTRACE, "Opening script %s ...\n", scriptname);
	    f = fopen(scriptname, "rb");
		  if (f == NULL) return -1;
			n = fread(userscript, 1, 1024*15-1, f);
	    userscript[n] = 0;
		  fclose(f);
	  }
		else if (!strncmp(scriptcontent, "scol://", 7))
	  {
			sprintf(script, "_load \"locked/slv.pkg\"\nmain \":%d\" \"%s\"", STDPORT, scriptname);
			MMechostr(MSKTRACE, "std user\n");
	    sprintf(userscript, "_load \"locked/stduser.pkg\"\nmain \"%s\" NIL NIL",
			scriptcontent);
	  }
		else
	  {
			sprintf(script, "_load \"locked/slv.pkg\"\nmain \":%d\" \"%s\"", STDPORT, scriptname);
			MMechostr(MSKTRACE, "script en parametre\n");
	    if (Mpushstrbloc(&mscol, scriptcontent)) return -1;
		  if (MBwebtostr(&mscol)) return -1;
			p = MMstartstr(&mscol, MMpull(&mscol)>>1);
			strcpy(userscript, p);
	  }
	}
    
  mscol.err = SCcreateappli(&mscol, NULL, script);
  tstscoldead(34);
	
	//$BLG - v5.22: Add
  mscol.lckdGC = 0;
	
	if ((ScolRights & M_RIGHTS) == 0) /* la machine doit-elle activer le cache d'office ? */
	{
		SCcacheActivate(&mscol); /* oui */
		strcpy(cookies, "__");    /* forcer le cookies à une valeur par défaut */
	}
    
  return 0;
}
