//----------------------------------------------------------------------
// Filename:    pkcssess.c
// Description: This file contains cryptoki session routines
//                              This file is machine-independent.
//
// Notice:              Copyright 1998 IBM Inc. All rights reserved.
//----------------------------------------------------------------------
//----------------------------------------
// includes
//----------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pkcsjnh.h"
#include "pkcsint.h"
#include "pkcsllf.h"

//
// Open session with token                  
//

CRYPTO_TOKEN_HANDLE PKCS_open_card_session(CK_CHAR_PTR pslot, CRYPTO_SESSION_INFO_PTR session_info) {  
    
    CRYPTO_TOKEN_HANDLE ptoken;

    DEBUG_MSG("Enter PKCS_open_card_session\n");
    DEBUG_INFO("Slot = %s\n", pslot);
//    DEBUG_INFO("Session_state %x\n", session_info->session_state);

    ptoken =  PKCS_open_card(pslot, session_info->session_state);

    DEBUG_MSG("Exit PKCS_open_card_session\n");
    return ptoken;

}


//
// Close session with token                  
//

CK_RV PKCS_close_card_session(CRYPTO_TOKEN_HANDLE ptoken) {  
    
      return fclose(ptoken);

}


// 
// Find an available session 
//

CK_SESSION_HANDLE	PKCS_Get_Available_Session(CRYPTO_SESSION_INFO_PTR * session_info_ptr, CK_ULONG cryptoki_sessions, CK_SLOT_ID yourslot, CK_ULONG maxslotsessions) {

	CK_SESSION_HANDLE	mysession = 0;
	CK_ULONG			i = 0, slotsessions = 0;
	CRYPTO_SESSION_INFO_PTR	session_ptr;
	
    DEBUG_MSG("Enter PKCS_Get_Available_Sessions\n");
	
	session_ptr = * session_info_ptr;

	DEBUG_INFO("session_ptr = %x\n", session_ptr);
	DEBUG_INFO("session_info_ptr = %x\n", session_info_ptr);

	// Find a free session
	while (i < cryptoki_sessions) {
		if (session_ptr == NULL_PTR) {
			DEBUG_INFO("%d is a free session\n", i+1);
			if (mysession == 0) {
				mysession = i + 1;
				DEBUG_INFO("Using %d as the session to return\n", mysession);
			}
		} else {
			if (yourslot == session_ptr->session_slot) {
					slotsessions++;
			}
		}
		i++;
		session_info_ptr++;
		session_ptr = * session_info_ptr;
	}

	// See if your token is already full
	DEBUG_INFO("Number of current slot sessions %d\n", slotsessions);
	if (slotsessions >= maxslotsessions) {
		DEBUG_INFO("Too many slot sessions, max = %d\n", maxslotsessions);
		mysession = 0;
	}

	// If out of sessions, may need to do a cleanup to make sure the sessions are actually active

	DEBUG_MSG("Exit PKCS_GetAvailable_Sessions\n");

	return mysession;
}


// 
// Return session handle of a single session open on a slot
// Otherwise return NULL.  This is useful if you need to know
// your session is the only one on this token. 
//

CK_SESSION_HANDLE	PKCS_Get_Exclusive_Session(CRYPTO_SESSION_INFO_PTR * session_info_ptr, CK_ULONG cryptoki_sessions, CK_SLOT_ID yourslot) {

	CK_SESSION_HANDLE	mysession = 0;
	CK_ULONG			i = 0, slotsessions = 0;
	CRYPTO_SESSION_INFO_PTR	session_ptr;
	
    DEBUG_MSG("Enter PKCS_Get_Exclusive_Session\n");
	
	session_ptr = * session_info_ptr;

	DEBUG_INFO("session_ptr = %x\n", session_ptr);
	DEBUG_INFO("session_info_ptr = %x\n", session_info_ptr);

	// Find a used session free session
	while (i < cryptoki_sessions) {
		if (session_ptr != NULL_PTR) {
			DEBUG_INFO("%d is a used session\n", i+1);
			if (yourslot == session_ptr->session_slot) {
				mysession = i + 1;
				slotsessions++;
				DEBUG_INFO("Session %d is for your slot\n", mysession);
			}
		}
		i++;
		session_info_ptr++;
		session_ptr = * session_info_ptr;
	}

	// See if your token is already full
	DEBUG_INFO("Number of current slot sessions %d\n", slotsessions);
	if (slotsessions != 1) {
		DEBUG_INFO("Too many slot sessions, number = %d\n", slotsessions);
		mysession = 0;
	}

	// If out of sessions, may need to do a cleanup to make sure the sessions are actually active

	DEBUG_MSG("Exit PKCS_Get_Exclusive_Session\n");

	return mysession;
}
