%%%----------------------------------------------------------------------------------------------------
%%% Description - This module is spawned for each of the session id generated. This module is called
%%% from handle_browser_packet and from all the components. This process in-turn spawns two more
%%% process called im_message and im_profile. The im_message process is used to send the messages
%%% to the client. The im_profile process is used to send the profile information of a particular
%%% user when requested by the client.
%%%----------------------------------------------------------------------------------------------------
-module(im_session).
-behaviour(gen_server).
-include("header.hrl").
-export([start/5, call_cast/12]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
%%%----------------------------------------------------------------------------------------------------
%%% External Function
%%%----------------------------------------------------------------------------------------------------
start(Config_Record, Session_ID, Publisher_ID, Protocol, Domain) ->
gen_server:start(?MODULE, [Config_Record, Session_ID, Publisher_ID, Protocol, Domain], []).
init([Config_Record, Session_ID, Publisher_ID, Protocol, Domain]) ->
if
Config_Record == undefined ->
Conf_Record = gen_server:call(load_config_record, get_config_record, infinity);
true ->
Conf_Record = Config_Record
end,
Connection_Map = dict:new(),
{ok, Box_PID} = im_message_box:start(Session_ID, self(), Publisher_ID, Protocol, Domain),
{ok, Profile_PID} = im_profile:start(self()),
process_table:store(Session_ID, self()),
{A, B, C} = erlang:now(),
random:seed(A, B, C),
MSNSessionID = random:uniform(16#FFFFFFFF),
MSNMessageID = random:uniform(16#FFFFFFFF),
{ok, #im_session_state{protocol = Protocol, domain = Domain, config_record = Conf_Record, connection_map = Connection_Map, publisher_id = Publisher_ID, remote_ip = "null", box_pid = Box_PID, session_id = Session_ID, used_services = [], profile_pid = Profile_PID, handle_packet_pid = -1, lifetime_ref = -1, msn_messageId = MSNMessageID, msn_sessionId = MSNSessionID, conference_id = 0, conference_details_list = []}}.
handle_call(get_pid, _From, State) ->
{reply, {ok, self()}, State};
handle_call(_, _, State) ->
{reply, "", State}.
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is called from the handle_browser_packet module. This method is the
%%% entry point for all the client requests
%%%
%%% Usage - {handle_request, #client_request(), XML Record, socket(), atom(), pid()}
%%% The 4th parameter is either http or https.
%%%----------------------------------------------------------------------------------------------------
handle_cast({handle_request, Client_Record, Request_Record, Send_Socket, Socket_Type, Handle_Packet_PID}, State) ->
io:format("im_session: Inside handle_request - Request_Record = ~n~p~n", [Request_Record]),
#im_session_state{config_record = Config_Record, lifetime_ref = Lifetime_Ref} = State,
if
Lifetime_Ref /= -1 ->
case timer:cancel(Lifetime_Ref) of
{ok, cancel} ->
?PRINT("Timer Cancelled ~n", []);
_ ->
?PRINT("Timer Not Cancelled ~n", [])
end,
case timer:apply_after(Config_Record#config_record.timeout, gen_server, cast, [self(), commit_suicide]) of
{ok, Ref} ->
?PRINT("Timer Reset ~n", []),
New_State = State#im_session_state{lifetime_ref = Ref, handle_packet_pid = Handle_Packet_PID};
_ ->
New_State = State#im_session_state{lifetime_ref = -1, handle_packet_pid = Handle_Packet_PID}
end;
true ->
case timer:apply_after(Config_Record#config_record.timeout, gen_server, cast, [self(), commit_suicide]) of
{ok, Ref} ->
?PRINT("Timer Reset ~n", []),
New_State = State#im_session_state{lifetime_ref = Ref, handle_packet_pid = Handle_Packet_PID};
_ ->
New_State = State#im_session_state{lifetime_ref = -1, handle_packet_pid = Handle_Packet_PID}
end
end,
{noreply, process_client_request(Client_Record, Request_Record, Send_Socket, Socket_Type, New_State)};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is called when the session idle timeout occurs
%%%----------------------------------------------------------------------------------------------------
handle_cast(commit_suicide, State) ->
?PRINT("Inside commit_suicide ~n", []),
commit_suicide(State),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the data to the client.
%%% Usage - {send_response, string(), socket(), integer(), atom(), string(), string(), pid())
%%% The 5th parameter is either http or https. The 7th parameter is either "close" or "keep-alive"
%%%----------------------------------------------------------------------------------------------------
handle_cast({send_response, Response, Socket, Socket_Type, Client_Record}, State) ->
#client_request{publisher_id = Publisher_ID, connection_type = Connection_Type, encoding = Encoding, callback = Handler, debug = Debug} = Client_Record,
#im_session_state{protocol = Protocol, session_id = Session_ID, handle_packet_pid = Handle_Packet_PID, domain = Domain} = State,
?PRINT("Inside send_response ~n", []),
Content = {im_server, [{session, State#im_session_state.session_id}], Response},
Content_String = protocol_wrapper:convert(Protocol, Content),
socket:send_data(Session_ID, Protocol, Socket, Socket_Type, Content_String, Encoding, Publisher_ID, Connection_Type, Handle_Packet_PID, Handler, Debug, Domain),
if
Connection_Type /= close andalso Protocol == "json" ->
?PRINT("################################ Send Response Successful (Socket Close) Socket ~p ################################ ~n~n", [Socket]),
socket:close(Socket_Type, Handle_Packet_PID, close, Socket);
true ->
nothing
end,
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to store the poll fd in im_message process, which is used to
%%% send the messages from server to client.
%%%
%%% Usage - {add_box_message_request, socket(), integer(), integer(), atom(), string(), pid()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_box_message_request, SD, Box_No, Encoding, Socket_Type, Connection_Type, Handle_Packet_PID, Handler, Debug}, State) ->
#im_session_state{box_pid = Box_PID} = State,
gen_server:cast(Box_PID, {add_box_message_request, SD, Box_No, Encoding, Socket_Type, Connection_Type, Handle_Packet_PID, Handler, Debug}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to store the messages in the im_message process.
%%% Usage - {add_message_to_box, string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_message_to_box, Message}, State) ->
#im_session_state{box_pid = Box_PID} = State,
gen_server:cast(Box_PID, {add_message_to_box, Message, false}),
{noreply, State};
handle_cast({add_message_to_box, Message, Delete_Session}, State) ->
#im_session_state{box_pid = Box_PID} = State,
gen_server:cast(Box_PID, {add_message_to_box, Message, Delete_Session}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to set the status of the components
%%% Usage - {set_status, integer(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({set_status, Status, Message}, State) ->
#im_session_state{connection_map = Connection_Map} = State,
?PRINT("Setting Status ~n", []),
Map_List = dict:to_list(Connection_Map),
lists:foreach(fun({_, PID}) ->
gen_server:cast(PID, {set_status, Status, Message})
end, Map_List),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method generates the progress message
%%% Usage - {add_progress, boolean(), string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_progress, Failure, Message, User_ID, Code, IM_Type}, State) ->
#im_session_state{publisher_id = Publisher_ID} = State,
?PRINT("Inside Add Progress ~n", []),
if
Failure == true ->
Length = length(Message),
if
Length == 0 ->
nothing;
true ->
Progress_Message = [{response, [{type, "progress"}, {im, IM_Type}, {login, User_ID}, {code, Code}], [Message]}],
gen_server:cast(self(), {add_message_to_box, Progress_Message}),
case gen_server:call(load_login_form, {get_login_form, false, Publisher_ID}) of
{ok, Login_Form} ->
gen_server:cast(self(), {add_message_to_box, Login_Form});
{error, _} ->
nothing
end
end;
true ->
Length = length(Message),
if
Length == 0 ->
nothing;
true ->
Progress_Message = [{response, [{type, "progress"}, {im, IM_Type}, {login, User_ID}, {code, Code}], [Message]}],
gen_server:cast(self(), {add_message_to_box, Progress_Message})
end
end,
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is called when the connection from the third party servers is closed
%%% abruptly. This method removes the process associated with that component and sends the fatal
%%% message to the client.
%%%
%%% Usage - {add_abrupt_close, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_abrupt_close, Code, Message, User_ID, IM_Type}, State) ->
io:format("Inside add_abrupt_close ~n"),
Message_Length = length(Message),
if
Message_Length /= 0 ->
Close_Message = [{response, [{type, "error"}, {errtype, "fatal"}, {im, IM_Type}, {login, User_ID}, {code, Code}], [Message]}];
true ->
Close_Message = [{response, [{type, "error"}, {errtype, "fatal"}, {im, IM_Type}, {login, User_ID}, {code, Code}], ["Disconnected From Server"]}]
end,
gen_server:cast(self(), {add_message_to_box, Close_Message}),
gen_server:cast(self(), {remove_im, IM_Type, User_ID, true}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used when the component processes are needed to be killed because
%%% they are no longer required. Also, the entry of the service from the connection map hash table
%%% is removed. If all the components are killed, the session process is also killed.
%%%
%%% Usage - {remove_im, string(), string(), boolean()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({remove_im, IM_Type, Login, Failure_Close}, State) ->
?PRINT("im_session: Inside remove_im ~n", []),
#im_session_state{connection_map = Connection_Map, session_id = Session_ID, used_services = Used_Services, remote_ip = Remote_IP, publisher_id = Publisher_ID} = State,
case dict:find(IM_Type, Connection_Map) of
{ok, IM_PID} ->
gen_server:call(IM_PID, {add_update_db, Remote_IP, Publisher_ID, "0", Session_ID}, infinity),
New_Connection_Map = dict:erase(IM_Type, Connection_Map),
New_Used_Services = lists:delete(IM_Type, Used_Services),
gen_server:cast(IM_PID, kill_connection);
error ->
New_Connection_Map = Connection_Map,
New_Used_Services = lists:delete(IM_Type, Used_Services)
end,
if
Failure_Close == false ->
Logout_Message = [{logout, [{im, IM_Type}, {login, Login}], []}],
gen_server:cast(self(), {add_message_to_box, Logout_Message});
true ->
nothing
end,
if
length(New_Used_Services) == 0 ->
gen_server:cast(self(), remove_session);
true ->
nothing
end,
{noreply, State#im_session_state{connection_map = New_Connection_Map, used_services = New_Used_Services}};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the tag. The tag means that the
%%% client needs to be reset.
%%% Usage - remove_session
%%%----------------------------------------------------------------------------------------------------
handle_cast(remove_session, State) ->
gen_server:cast(self(), {add_message_to_box, [?IM_LOGOUT_TAG], true}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method sends the non fatal error response
%%% Usage - {send_nonfatal_error_response, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({send_nonfatal_error_response, Code, Message, User_ID, IM_Type}, State) ->
Error_Message = [{response, [{type, "error"}, {errtype, "nonfatal"}, {im, IM_Type}, {login, User_ID}, {code, Code}], [Message]}],
gen_server:cast(self(), {add_message_to_box, Error_Message}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the buddy list to the client at the time of login.
%%% Usage - {add_data, string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_data, Data, User_ID, IM_Type}, State) ->
Buddy_String = [{buddies, [{im, IM_Type}, {login, User_ID}], Data}],
gen_server:cast(self(), {add_message_to_box, Buddy_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the updated status of a buddy to the client
%%% Usage - {add_status, string(), string(), string(), integer(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_status, From, To, Group, Status, Msg, Blocked, IM_Type}, State) ->
gen_server:cast(self(), {add_status, From, "", To, Group, Status, Msg, Blocked, IM_Type}),
{noreply, State};
handle_cast({add_status, From, Alias, To, Group, Status, Msg, Blocked, IM_Type}, State) ->
?PRINT("Inside Add Status ~n", []),
case regexp:gsub(Msg, "\r", "") of
{ok, Modified_Msg_1, _} ->
New_Message_1 = Modified_Msg_1;
_ ->
New_Message_1 = Msg
end,
case regexp:gsub(New_Message_1, "\n", "") of
{ok, Modified_Msg_2, _} ->
Message = Modified_Msg_2;
_ ->
Message = New_Message_1
end,
Length = length(Message),
case Status of
?IM_OFFLINE ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_OFFLINE_STR
end,
Status_String = ?IM_OFFLINE_STATUS_STR;
?IM_AVAILABLE ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_ONLINE_STR
end,
Status_String = ?IM_ONLINE_STATUS_STR;
?IM_BUSY ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_BUSY_STR
end,
Status_String = ?IM_BUSY_STATUS_STR;
?IM_IDLE ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_IDLE_STR
end,
Status_String = ?IM_IDLE_STATUS_STR;
?IM_AWAY ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_AWAY_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_BRB ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_BRB_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_ON_PHONE ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_ON_PHONE_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_OUT_FOR_LUNCH ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_OUT_FOR_LUNCH_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_VACATION ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_VACATION_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_NOT_AT_HOME ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_NOT_AT_HOME_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_NOT_AT_OFFICE ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_NOT_AT_OFFICE_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_NOT_AT_DESK ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_NOT_AT_DESK_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_STEPPED_OUT ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_STEPPED_OUT_STR
end,
Status_String = ?IM_AWAY_STATUS_STR;
?IM_CUSTOM ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = "none"
end,
Status_String = ?IM_AWAY_STATUS_STR;
_ ->
if
Length > 0 ->
Custom_String = Message;
true ->
Custom_String = ?IM_AWAY_STR
end,
Status_String = ?IM_AWAY_STATUS_STR
end,
if
Blocked == true ->
Blocked_String = "yes";
true ->
Blocked_String = "no"
end,
Update_String = [{update, [{im, IM_Type}, {login, To}, {group, Group}, {name, From}, {alias, Alias}, {status, Status_String}, {custom, Custom_String}, {blocked, Blocked_String}], []}],
gen_server:cast(self(), {add_message_to_box, Update_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the typing indication to the client
%%% Usage - {add_typing_indicator, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_typing_indicator, From, To, Typing_State, IM_Type}, State) ->
if
Typing_State == 1 ->
Typing_Type = "start";
true ->
Typing_Type = "stop"
end,
Typing_String = [{typing, [{type, Typing_Type}, {im, IM_Type}, {login, To}, {name, From}], []}],
gen_server:cast(self(), {add_message_to_box, Typing_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send message to the client
%%% Usage - {add_message, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_message, From, From_Alias, To, Msg, Time, IM_Type}, State) ->
#im_session_state{protocol = Protocol} = State,
case regexp:gsub(Msg, "\r", "") of
{ok, Modified_Msg_1, _} ->
New_Message_1 = Modified_Msg_1;
_ ->
New_Message_1 = Msg
end,
case regexp:gsub(New_Message_1, "\n", "") of
{ok, Modified_Msg_2, _} ->
Message = Modified_Msg_2;
_ ->
Message = New_Message_1
end,
if
IM_Type == "msn" ->
Is_Unicode = is_unicode(Message),
if
Is_Unicode == true ->
New_Message = xmerl_ucs:to_utf8(Message);
true ->
New_Message = Message
end;
true ->
New_Message = Message
end,
if
Protocol == "json" ->
Message_String = [{message, [{im, IM_Type}, {login, To}, {name, From}, {alias, From_Alias}, {time, Time}], [find_and_replace:characters([], New_Message)]}];
true ->
Message_String = [{message, [{im, IM_Type}, {login, To}, {name, From}, {alias, From_Alias}, {time, Time}], [New_Message]}]
end,
gen_server:cast(self(), {add_message_to_box, Message_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send feeds to the client
%%% Usage - {add_feeds, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_feeds, Type, From, To, Next, Feeds, IM_Type}, State) ->
Feed_String = [{feeds, [{im, IM_Type}, {login, To}, {name, From}, {type, Type}, {next, Next}], [xmerl_ucs:to_utf8(Feeds)]}],
gen_server:cast(self(), {add_message_to_box, Feed_String}),
{noreply, State};
handle_cast({add_chat_history, Login, UID, IM_Type, Chat_Message}, State) ->
Chat_History = [{chat_history, [{im, IM_Type}, {login, Login}, {uid, UID}], Chat_Message}],
gen_server:cast(self(), {add_message_to_box, Chat_History}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the accept information to the client, when a buddy
%%% accepts the friendship request sent by the IM Server.
%%% Usage - {add_buddy_confirm, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_buddy_confirm, From, To, _Message, IM_Type}, State) ->
Add_Buddy_String = [{buddyapprove, [{im, IM_Type}, {login, To}, {name, From}, {type, "confirm"}], []}],
gen_server:cast(self(), {add_message_to_box, Add_Buddy_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the deny information to the client, when a buddy
%%% rejects the friendship request sent by the IM Server.
%%% Usage - {add_buddy_deny, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_buddy_deny, From, To, _Message, IM_Type}, State) ->
Add_Buddy_String = [{buddyapprove, [{im, IM_Type}, {login, To}, {name, From}, {type, "deny"}], []}],
gen_server:cast(self(), {add_message_to_box, Add_Buddy_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send the invalid information to the client, when a
%%% request like add/remove/block has generated an error on the third party servers.
%%% Usage - {add_buddy_invalid, string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_buddy_invalid, From, To, IM_Type}, State) ->
Invalid_Buddy_String = [{buddyapprove, [{im, IM_Type}, {login, To}, {name, From}, {type, "invalid"}], []}],
gen_server:cast(self(), {add_message_to_box, Invalid_Buddy_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used when the deletion of a group is not successful. By default, when
%%% a group is deleted, the client removes the group without waiting for the successful removal of the
%%% group at the server end. So, if the group removal is not successful, the server sends the list of
%%% buddies that are not removed. to the client.
%%% Usage - {add_buddy_to_client, string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_buddy_to_client, Data, User_ID, IM_Type}, State) ->
Add_Buddy_String = [{add_buddies, [{im, IM_Type}, {login, User_ID}], Data}],
gen_server:cast(self(), {add_message_to_box, Add_Buddy_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used when the renaming of a group is not successful. By default, when
%%% a group is renamed, the client renames the group without waiting for the successful renaming of the
%%% group at the server end. So, if the group renaming is not successful, the server asks the client
%%% to change back to the old group.
%%% Usage - {add_rename_group, string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_rename_group, Old_Group, New_Group, User_ID, IM_Type}, State) ->
Rename_Group_String = [{rename_group, [{im, IM_Type}, {login, User_ID}, {old_group, Old_Group}, {new_group, New_Group}], []}],
gen_server:cast(self(), {add_message_to_box, Rename_Group_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used the addition of a group is not successful.
%%% Usage - {add_remove_group, string(), string(), string()}
%----------------------------------------------------------------------------------------------------
handle_cast({add_remove_group, Group, User_ID, IM_Type}, State) ->
Remove_Group_String = [{remove_group, [{im, IM_Type}, {login, User_ID}, {group, Group}], []}],
gen_server:cast(self(), {add_message_to_box, Remove_Group_String}),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used a contact cannot be moved.
%%% Usage - {add_move_contact, string(), string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_move_contact, Buddy_Name, Old_Group, New_Group, User_ID, IM_Type}, State) ->
Move_Contact_String = [{move_contact, [{im, IM_Type}, {login, User_ID}, {name, Buddy_Name}, {old_group, Old_Group}, {new_group, New_Group}], []}],
gen_server:cast(self(), {add_message_to_box, Move_Contact_String}),
{noreply, State};
%begin file transfer work
handle_cast({add_ask_file_transfer, Buddy_Name, File_Name, Key, User_ID, IM_Type}, State) ->
Ask_File_Transfer_String = [{file, [{im, IM_Type}, {login, User_ID}, {name, Buddy_Name}, {file_name, File_Name}, {file_size, []}, {key, Key}, {type, "ask"}, {content, []}], []}],
gen_server:cast(self(), {add_message_to_box, Ask_File_Transfer_String}),
{noreply, State};
handle_cast({add_receive_file, Buddy_Name, File_Name, User_ID, IM_Type}, State) ->
%os:cmd("chmod 777 /var/www/file_receive/" ++ File_Name),
%os:cmd("chown narasimham:narasimham /var/www/file_receive/" ++ File_Name),
Receive_File_String = [{file, [{im, IM_Type}, {login, User_ID}, {name, Buddy_Name}, {file_name, File_Name}, {file_size, []}, {key, []}, {type, "receive"}], []}],
gen_server:cast(self(), {add_message_to_box, Receive_File_String}),
{noreply, State};
%end file transfer work
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to store the statistics information.
%%% Usage - {add_update_db, string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({add_update_db, Login, IM_Type, Connection_Type}, State) ->
#im_session_state{session_id = Session_ID, publisher_id = Publisher_ID, remote_ip = Remote_IP} = State,
Session_Query = io_lib:format("insert into session_login_info values('~s', '~s', '~s', '~s')", [Session_ID, IM_Type, Login, time:seconds_from_year_zero()]),
db_manager:update_db(Session_Query),
Stats_Query = "call add_stats('" ++ Login ++ "', '" ++ IM_Type ++ "', " ++ Connection_Type ++ ", '" ++ Remote_IP ++ "', '" ++ Publisher_ID ++ "')",
db_manager:update_db(Stats_Query),
{noreply, State};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to send referral to Yahoo buddies
%%% Usage - {send_referral, [@buddies()], string(), string(), string(), string(), string(), string(), string(), string(), string()}
%%%----------------------------------------------------------------------------------------------------
handle_cast({send_referral, [HeadBuddy = {buddies, [IM_Type], [_From], [To]}|BuddyTail], Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer}, State) ->
#im_session_state{connection_map = Connection_Map, progress = Progress, progress_rate = Progress_Rate} = State,
New_Progress = Progress + Progress_Rate,
case send_referral(HeadBuddy, Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer) of
{ok, Msg} ->
case dict:find(IM_Type, Connection_Map) of
{ok, PID} ->
Response = [{referral, [{progress, integer_to_list(round(New_Progress))}], []}],
gen_server:cast(PID, {send_message, To, ?MSG_CHAT, Msg});
error ->
Progress_Response = [{referral, [{progress, integer_to_list(round(New_Progress))}], []}],
Response = [{response, [{type, "error"}, {errtype, "client"}, {im, IM_Type}, {code, "104"}], ["Message Send Failure"]}] ++ Progress_Response
end;
_ ->
Progress_Response = [{referral, [{progress, integer_to_list(round(New_Progress))}], []}],
Response = [{response, [{type, "error"}, {errtype, "client"}, {im, IM_Type}, {code, "104"}], ["Message Send Failure"]}] ++ Progress_Response
end,
gen_server:cast(self(), {add_message_to_box, Response}),
timer:apply_after(500, ?MODULE, call_cast, [send_referral, BuddyTail, Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer, self()]),
{noreply, State#im_session_state{progress=New_Progress}};
handle_cast({send_referral, [_HeadBuddy|BuddyTail], Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer}, State) ->
gen_server:cast(self(), {send_referral, BuddyTail, Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer}),
{noreply, State};
handle_cast({send_referral, [], _, _, _, _, _, _, _, _, _}, State) ->
{noreply, State};
%begin conference related code (handling casts from service pids)
%begin narasimham conference handling
handle_cast({add_message_to_conference,ConferenceId,LoginName,MessageFrom,Msg,IM_Type,Service},State) ->
case lists:keysearch(ConferenceId,1,State#im_session_state.conference_details_list) of
{value,{_NewConferenceId,HostName,HostService,ServicesList}} ->
case regexp:gsub(Msg, "\r", "") of
{ok, Modified_Msg_1, _} ->
New_Message_1 = Modified_Msg_1;
_ ->
New_Message_1 = Msg
end,
case regexp:gsub(New_Message_1, "\n", "") of
{ok, Modified_Msg_2, _} ->
Message1 = Modified_Msg_2;
_ ->
Message1 = New_Message_1
end,
if
IM_Type == "msn" ->
Is_Unicode = is_unicode(Message1),
if
Is_Unicode == true ->
Message = xmerl_ucs:to_utf8(Message1);
true ->
Message = Message1
end;
true ->
Message = Message1
end,
Connection_Map = State#im_session_state.connection_map,
%% unify the message to all services here
TaggedMessage = find_and_replace:words(Msg),
TokenizedMessage= html_tokenise:string2toks(TaggedMessage),
RawMessage = lists:flatten(lists:reverse(get_raw_message(TokenizedMessage))),
UnifiedMessage1 = io_lib:format(">~s",[RawMessage]),
UnifiedMessage2 = ["<font color=","\"#000000","\"",UnifiedMessage1,"</font",">"],
A = lists:flatten(UnifiedMessage2),
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
UnifiedMsg = str:append(B, lists:sublist(A, 39, length(A))),
cast_join_leave_message_to_other_services(ServicesList,IM_Type,LoginName,ConferenceId,UnifiedMsg,Connection_Map),
case IM_Type == "msn" orelse IM_Type == "yah" orelse IM_Type == "jab" of
true ->
case regexp:split(Message, MessageFrom ++ " says:") of
{ok, [[],Field]} ->
WebIMClientMsg = Field;
{ok, [Field1,Field2]} ->
WebIMClientMsg = Field1 ++ " " ++ Field2;
_->
WebIMClientMsg = Message
end;
_->
WebIMClientMsg = Message
end,
Message_String = [{conf, [{hostname, HostName}, {hostservice, HostService}, {id, ConferenceId}, {operation, "message"}],
[{conference,[{im, IM_Type}, {login, LoginName}, {service, Service}, {name, MessageFrom}],
[{message,[],[WebIMClientMsg]}]}]}],
gen_server:cast(self(), {add_message_to_box,Message_String});
false ->
io:format("im_session: add_message_to_conference clause Conference does not exists with id ~p ~n",[ConferenceId])
end,
{noreply, State};
handle_cast({typing_indicator_to_conference,ConferenceId,LoginName,TypingUser,TypingState,IM_Type},State)->
if
TypingState == 1 ->
Typing_Type = "start";
true ->
Typing_Type = "stop"
end,
Typing_String = [{conference, [{im, IM_Type}, {login, LoginName}, {id, ConferenceId}, {operation, "typing_indicator"}, {time, []}, {name, TypingUser}, {type, Typing_Type}], []}],
gen_server:cast(self(), {add_message_to_box, Typing_String}),
{noreply, State};
handle_cast({buddy_joins_conference,ConferenceId,LoginName,UserJoined,IM_Type,Service},StateData)->
io:format("im_session: ~n~p~n",[{buddy_joins_conference,ConferenceId,LoginName,UserJoined,IM_Type,Service}]),
Connection_Map = StateData#im_session_state.connection_map,
case lists:keysearch(ConferenceId,1,StateData#im_session_state.conference_details_list) of
{value,{NewConferenceId,HostName,HostService,ServicesList}} ->
String = [{conf, [{hostname, HostName}, {hostservice, HostService}, {id, NewConferenceId}, {operation, "join"}], [{conference,[{im, IM_Type}, {login, LoginName}, {service, Service}, {name, UserJoined}], []}]}],
gen_server:cast(self(),{add_message_to_box, String}),
%% formattiing the message to send to services
TempMessage1 = io_lib:format(">Buddy ~s says ~s has joined the conference/conversation ",[HostName,UserJoined]),
TempMessage2 = ["<font color=","\"#000000","\"",TempMessage1,"</font",">"],
A = lists:flatten(TempMessage2),
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
Message = str:append(B, lists:sublist(A, 39, length(A))),
cast_join_leave_message_to_other_services(ServicesList,IM_Type,LoginName,ConferenceId,Message,Connection_Map),
%% update the conference_details_list - mean add 1 to the count per particular service where buddy joined
%% should i inform the newly joined about existing memebers in the conference
Temp = lists:delete({NewConferenceId,HostName,HostService,ServicesList},StateData#im_session_state.conference_details_list),
case lists:keysearch(IM_Type,1,ServicesList) of
{value,{TypeIM,IMLogin,Count,List}} ->
Temp2 = lists:delete({TypeIM,IMLogin,Count,List},ServicesList),
NewServicesList = [{TypeIM,IMLogin,Count + 1, [UserJoined | lists:delete(UserJoined,List)]} | Temp2];
false ->
io:format("im_session: MSN/Gtalk buddies have joined the conference ~n"),
NewServicesList = [{IM_Type,LoginName,1,[UserJoined]} | ServicesList]
end,
NewConference_Details_List = [{NewConferenceId,HostName,HostService,NewServicesList} | Temp],
NewStateData = StateData#im_session_state{conference_details_list = NewConference_Details_List};
false ->
io:format("~n ~n im_session: Remote MSN or GTalk Buddy initiated the conference i think ~n ~n"),
Temp = StateData#im_session_state.conference_details_list,
NewConferenceDetailsList = [{ConferenceId,LoginName,IM_Type,[{IM_Type,LoginName,1,[UserJoined]}]} | Temp],
String = [{conf,[{hostname, LoginName}, {hostservice, IM_Type}, {id, ConferenceId}, {operation, "join"}], [{conference,[{im, IM_Type}, {login, LoginName}, {service, Service}, {name, UserJoined}], []}]}],
gen_server:cast(self(),{add_message_to_box, String}),
NewStateData = StateData#im_session_state{conference_details_list = NewConferenceDetailsList}
end,
{noreply,NewStateData};
handle_cast({buddy_leaves_conference,ConferenceId,LoginName,UserLeft,IM_Type,Service}, StateData)->
case lists:keysearch(ConferenceId,1,StateData#im_session_state.conference_details_list) of
{value, {NewConferenceId,HostName,HostService,ServicesList}} ->
String = [{conf,[{hostname, HostName}, {hostservice, HostService}, {id, ConferenceId}, {operation, "leave"}],[{conference,[{im, IM_Type}, {login, LoginName}, {service, Service}, {name, UserLeft}],[]}]}],
gen_server:cast(self(),{add_message_to_box, String}),
%% formattiing the message to send to services
TempMessage1 = io_lib:format(">Buddy ~s says ~s has left the conference/conversation ",[HostName,UserLeft]),
TempMessage2 = ["<font color=","\"#000000","\"",TempMessage1,"</font",">"],
A = lists:flatten(TempMessage2),
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
Message = str:append(B, lists:sublist(A, 39, length(A))),
Connection_Map = StateData#im_session_state.connection_map,
cast_join_leave_message_to_other_services(ServicesList,IM_Type,LoginName,ConferenceId,Message,Connection_Map),
%% update the conference_details_list - mean subtract 1 from the count per particular service where buddy joined
Temp = lists:delete({NewConferenceId,HostName,HostService,ServicesList},StateData#im_session_state.conference_details_list),
case lists:keysearch(IM_Type,1,ServicesList) of
{value,{TypeIM,IMLogin,Count,Members}} ->
io:format("buddies leaving the conference........ ~n~n~n~p~n~n~n",[{TypeIM,IMLogin,Count,Members}]),
Temp2 = lists:delete({TypeIM,IMLogin,Count,Members},ServicesList),
if
Count >= 1 ->
NewServicesList = [{TypeIM,IMLogin, Count-1, lists:delete(UserLeft,Members)} | Temp2],
NewConference_Details_List = [{NewConferenceId,HostName,HostService,NewServicesList} | Temp];
true ->
io:format("im_session: Mebers count in the conference from service ~p is ~p ~n",[TypeIM,Count]),
NewServicesList = Temp2,
NewConference_Details_List = [{NewConferenceId,HostName,HostService,NewServicesList} | Temp]
end;
false ->
NewServicesList = ServicesList,
NewConference_Details_List = [{NewConferenceId,HostName,HostService,NewServicesList} | Temp]
end,
NewStateData = StateData#im_session_state{conference_details_list = NewConference_Details_List};
false ->
io:format("~n ~n im_session: Hello check up the cast statement in user_leave_conference cast statement ~n ~n"),
NewStateData = StateData
end,
{noreply,NewStateData};
handle_cast({accept_request,ConferenceId,LoginName,InvitationFrom,IM_Type,Service,Message},StateData)->
io:format("im_session: got accept_request for conf ~s from service im_~s ~n",[ConferenceId,IM_Type]),
Message_String = [{conf, [{hostname, LoginName}, {hostservice, IM_Type}, {id, ConferenceId}, {operation, "accept_request"}],
[{conference, [{im, IM_Type}, {login, LoginName}, {service, Service}, {name, InvitationFrom}],
[{message,[],[Message]}]}]}],
gen_server:cast(self(), {add_message_to_box,Message_String}),
{noreply,StateData};
%% no need to send accept notification to client
handle_cast({reject,ConferenceId,LoginName,RejectFrom,IM_Type,Service},StateData)->
case lists:keysearch(ConferenceId,1,StateData#im_session_state.conference_details_list) of
{value,{NewConferenceId,HostName,HostService,_ServicesList}} ->
Message_String = [{conf, [{hostname, HostName}, {hostservice, HostService}, {id, NewConferenceId}, {operation, "reject"}],
[{conference,[{im, IM_Type}, {login, LoginName}, {service, Service}, {name, RejectFrom}],
[]}]}],
gen_server:cast(self(), {add_message_to_box,Message_String});
false ->
%% reply back to yahoo saying that conference doesn't exist
io:format("im_session: Can a service cast to a conference that does not exist~n")
end,
{noreply,StateData};
%%end conference related code
handle_cast({commit_suicide, State}, _) ->
io:format("im_session: commit_suicide~n"),
{stop, normal, State};
handle_cast(kill_process, State) ->
io:format("im_session: kill_process~n"),
{stop, normal, State};
handle_cast(_, State)->
{noreply, State}.
handle_info({'EXIT', _Pid, _}, State) ->
{noreply, State};
handle_info(_, State) ->
{noreply, State}.
terminate(_, State) ->
#im_session_state{protocol = Protocol, domain = Domain, box_pid = Box_PID, profile_pid = Profile_PID, publisher_id = Publisher_ID, session_id = Session_ID, handle_packet_pid = Handle_Packet_PID} = State,
Box_State = gen_server:call(Box_PID, get_message_box_state, infinity),
#im_message_box_state{poll_sd_list = Poll_SD_List} = Box_State,
if
Poll_SD_List /= "" ->
[Poll_Info_Record | _] = Poll_SD_List,
#poll_info{socket = Poll_SD, encoding = Encoding, socket_type = Socket_Type, handler = Handler, debug = Debug} = Poll_Info_Record,
spawn(send_login_form, timeout, [Publisher_ID, Poll_SD, true, Encoding, Socket_Type, Protocol, Handle_Packet_PID, Handler, Debug, Domain]);
true ->
gen_server:cast(Handle_Packet_PID, kill_process)
end,
kill_child_process(State),
process_table:remove(Session_ID),
gen_server:cast(Box_PID, kill_process),
gen_server:cast(Profile_PID, kill_process),
Query = io_lib:format("delete from session_info where session_id = '~s'", [Session_ID]),
db_manager:update_db(Query),
?PRINT("Session Process Killed ~n", []).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
process_client_request(Client_Record, _, Send_Socket, Socket_Type, State) when Client_Record#client_request.session == "" andalso Client_Record#client_request.request_len == "0" ->
?PRINT("Request Length = 0 & Session ID = \"\" ~n", []),
#client_request{connection_type = Connection_Type} = Client_Record,
#im_session_state{handle_packet_pid = Handle_Packet_PID} = State,
socket:close(Socket_Type, Handle_Packet_PID, Connection_Type, Send_Socket),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the client request. This method is called when the
%%% length of the client request is "0". This means that the client is asking for the buddy list again.
%%% So, the server sends the buddy list again to the client.
%%%
%%% Usage - process_client_request(#client_request(), XML Record, socket(), atom(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_client_request(Client_Record, _, Send_Socket, Socket_Type, State) when Client_Record#client_request.type == "none" andalso Client_Record#client_request.request_len == "0" ->
#client_request{encoding = Encoding, callback = Handler, debug = Debug} = Client_Record,
#im_session_state{protocol = Protocol, used_services = Used_Services, handle_packet_pid = Handle_Packet_PID, domain = Domain} = State,
L1 = length(Used_Services),
if
L1 > 0 ->
Buddy_List_String = lists:foldl(fun(IM_Type, Buddy_String) ->
case dict:find(IM_Type, State#im_session_state.connection_map) of
{ok, PID} ->
{List, User_ID} = gen_server:call(PID, get_buddy_list, infinity),
Buddy_List = [{buddies, [{im, IM_Type}, {login, User_ID}], List}],
str:append(Buddy_String, Buddy_List);
_ ->
Buddy_String
end end, "", Used_Services),
New_Buddy_List_String = [{box, [{start, "0"}, {next, "0"}], []}] ++ Buddy_List_String ++ get_conference_details_list(State#im_session_state.conference_details_list),
gen_server:cast(self(), {send_response, New_Buddy_List_String, Send_Socket, Socket_Type, Client_Record});
true ->
spawn(send_login_form, start, [Client_Record, Send_Socket, true, Encoding, Socket_Type, Protocol, Handle_Packet_PID, Handler, Debug, Domain])
end,
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the client request.
%%% Usage - process_client_request(#client_request(), XML Record, socket(), atom(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_client_request(Client_Record, Request_Record, Send_Socket, Socket_Type, State) when Client_Record#client_request.type == "none" ->
Processed_Atleast_One_Record = false,
handle_request(Request_Record, Client_Record, Processed_Atleast_One_Record, Send_Socket, Socket_Type, State);
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the client request. This method sends the login form
%%% to the client.
%%% Usage - process_client_request(#client_request(), XML Record, socket(), atom(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_client_request(Client_Record, _, Send_Socket, Socket_Type, State) when Client_Record#client_request.type == "loginform" ->
#client_request{publisher_id = Publisher_ID, connection_type = Connection_Type} = Client_Record,
#im_session_state{handle_packet_pid = Handle_Packet_PID} = State,
case gen_server:call(load_login_form, {get_login_form, false, Publisher_ID}, infinity) of
{ok, Login_Form} ->
gen_server:cast(self(), {send_response, Login_Form, Send_Socket, Socket_Type, Client_Record});
error ->
socket:close(Socket_Type, Handle_Packet_PID, Connection_Type, Send_Socket)
end,
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the client request. This method retrieves the profile
%%% of a particular buddy.
%%% Usage - process_client_request(#client_request(), XML Record, socket(), atom(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_client_request(Client_Record, _, Send_Socket, Socket_Type, State) when Client_Record#client_request.type == "profile" ->
#im_session_state{profile_pid = Profile_PID} = State,
gen_server:cast(Profile_PID, {get_profile, Send_Socket, Socket_Type, Client_Record, State}),
State;
process_client_request(Client_Record, _, Send_Socket, Socket_Type, State) ->
?PRINT("Not Handled Now ~n", []),
#client_request{connection_type = Connection_Type} = Client_Record,
#im_session_state{handle_packet_pid = Handle_Packet_PID} = State,
socket:close(Socket_Type, Handle_Packet_PID, Connection_Type, Send_Socket),
State.
handle_request([], Client_Record, Processed_Atleast_One_Record, Send_Socket, Socket_Type, State) ->
#client_request{connection_type = Connection_Type} = Client_Record,
#im_session_state{handle_packet_pid = Handle_Packet_PID} = State,
if
Processed_Atleast_One_Record == false ->
socket:close(Socket_Type, Handle_Packet_PID, Connection_Type, Send_Socket);
true ->
nothing
end,
State;
handle_request([Request_Record|Next_Record], Client_Record, _, Send_Socket, Socket_Type, State) ->
New_State= process_request([Request_Record|""], Client_Record, Send_Socket, Socket_Type, State),
handle_request(Next_Record, Client_Record, true, Send_Socket, Socket_Type, New_State).
process_request([], Client_Record, Send_Socket, Socket_Type, State) ->
#client_request{connection_type = Connection_Type} = Client_Record,
#im_session_state{handle_packet_pid = Handle_Packet_PID} = State,
socket:close(Socket_Type, Handle_Packet_PID, Connection_Type, Send_Socket),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the contacts XML request.
%%% Usage - process_request(#contacts(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{contacts, _}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{config_record = Config_Record, connection_map = Connection_Map, used_services = Used_Services} = State,
Response = [{response, [{type, "success"}], []}],
#config_record{addr_book_url = Addr_Book_URL} = Config_Record,
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
get_contacts(Used_Services, Connection_Map, Addr_Book_URL),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the login XML request
%%% Usage - process_request(#login(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{login, {login, [Type], [Login_Name], [Pass], [Mode], _}}], Client_Record, Send_Socket, Socket_Type, State) when Type == "" orelse Login_Name == "" orelse Pass == "" orelse Mode == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{login, {login, IM_Type, Login_Name, Pass, Mode, _}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == ["yah"] orelse IM_Type == ["aim"] orelse IM_Type == ["msn"] orelse IM_Type == ["icq"] orelse IM_Type == ["jab"] orelse IM_Type == ["wim"] orelse IM_Type == ["fbk"] ->
#client_request{publisher_id = Publisher_ID, encoding = Encoding, remote_ip = Remote_IP} = Client_Record,
#im_session_state{config_record = Config_Record, connection_map = Connection_Map, used_services = Used_Services, session_id = Session_ID} = State,
Service = lists:flatten(IM_Type),
Login = xmerl_ucs:to_utf8(lists:flatten(Login_Name)),
Prv = Config_Record#config_record.prv,
Mod = Config_Record#config_record.mod,
Password_Encrypted = Config_Record#config_record.password_encrypted,
if
Password_Encrypted == "yes" ->
Decrypted_Password = rsa:decrypt(lists:flatten(Pass), Prv, Mod);
true ->
Decrypted_Password = lists:flatten(Pass)
end,
case dict:find(Service, Connection_Map) of
{ok, Old_PID} ->
gen_server:cast(Old_PID, kill_connection);
_ ->
nothing
end,
Modified_Connection_Map = dict:erase(Service, Connection_Map),
Modified_Used_Services = lists:delete(Service, Used_Services),
case Service of
"yah" ->
Yahoo_Encryption_Server = Config_Record#config_record.yahoo_encryption_server,
Yahoo_Encryption_Port = Config_Record#config_record.yahoo_encryption_port,
File_Send_Directory = Config_Record#config_record.file_send_directory,
File_Receive_Directory = Config_Record#config_record.file_receive_directory,
case im_yahoo:start(Session_ID, self(), Yahoo_Encryption_Server, Yahoo_Encryption_Port, File_Send_Directory, File_Receive_Directory) of
{ok, PID} ->
case catch gen_server:call(PID, {create_connection, Login}, 60000) of
{ok, Response} ->
Conn_Map = dict:store("yah", PID, Modified_Connection_Map),
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:call(PID, {login, Login, Decrypted_Password, lists:flatten(Mode)}, infinity),
State#im_session_state{connection_map = Conn_Map, publisher_id = Publisher_ID, remote_ip = Remote_IP, used_services = str:append(Modified_Used_Services, ["yah"|""])};
{error, Response} ->
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "yah", Login, true}),
State;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "yah"}, {code, "108"}, {login, Login}], ["Server Connection Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "yah", Login, true}),
State
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "yah"}, {code, "103"}, {login, Login}], ["Error in IM Server Component"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {remove_im, "yah", Login, true}),
State
end;
"aim" ->
case im_aim:start(Session_ID, self()) of
{ok, PID} ->
case catch gen_server:call(PID, {create_connection, Login}, 30000) of
{ok, Response} ->
Conn_Map = dict:store("aim", PID, Modified_Connection_Map),
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:call(PID, {set_login_details, Login, Decrypted_Password, lists:flatten(Mode)}),
State#im_session_state{connection_map = Conn_Map, publisher_id = Publisher_ID, remote_ip = Remote_IP, used_services = str:append(Modified_Used_Services, ["aim"|""])};
{error, Response} ->
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "aim", Login, true}),
State;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "aim"}, {code, "108"}, {login, Login}], ["Server Connection Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "aim", Login, true}),
State
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "aim"}, {code, "103"}, {login, Login}], ["Error in IM Server Component"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {remove_im, "aim", Login, true}),
State
end;
"icq" ->
case im_icq:start(Session_ID, self()) of
{ok, PID} ->
case catch gen_server:call(PID, {create_connection, Login, Decrypted_Password}, 120000) of
{ok, Response} ->
Conn_Map = dict:store("icq", PID, Modified_Connection_Map),
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:call(PID, {set_login_details, Login, Decrypted_Password, lists:flatten(Mode)}),
State#im_session_state{connection_map = Conn_Map, publisher_id = Publisher_ID, remote_ip = Remote_IP, used_services = str:append(Modified_Used_Services, ["icq"|""])};
{error, Response} ->
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "icq", Login, true}),
State;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "icq"}, {code, "108"}, {login, Login}], ["Server Connection Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "icq", Login, true}),
State
end;
true ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "icq"}, {code, "103"}, {login, Login}], ["Error in IM Server Component"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {remove_im, "icq", Login, true}),
State
end;
"msn" ->
case im_msn:start(self(),Config_Record#config_record.file_send_directory,Config_Record#config_record.file_receive_directory,State#im_session_state.msn_messageId + 2000,State#im_session_state.msn_sessionId + 2000) of
{ok, PID} ->
case catch gen_server:call(PID, {connect, Login, Decrypted_Password}, 60000) of
{ok, Response} ->
Conn_Map = dict:store("msn", PID, Modified_Connection_Map),
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State#im_session_state{connection_map = Conn_Map, publisher_id = Publisher_ID, remote_ip = Remote_IP, used_services = str:append(Modified_Used_Services, ["msn"|""]),msn_messageId=State#im_session_state.msn_messageId + 2000,msn_sessionId = State#im_session_state.msn_sessionId + 2000};
{fail, Response} ->
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "msn", Login, true}),
State;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "msn"}, {code, "108"}, {login, Login}], ["Server Connection Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "msn", Login, true}),
State
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "msn"}, {code, "103"}, {login, Login}], ["Error in IM Server Component"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {remove_im, "msn", Login, true}),
State
end;
"fbk" ->
case im_facebook:start(self()) of
{ok, PID} ->
case catch gen_server:call(PID, {login, Login, Decrypted_Password}, 120000) of
{ok, Response} ->
Conn_Map = dict:store("fbk", PID, Modified_Connection_Map),
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State#im_session_state{connection_map = Conn_Map, publisher_id = Publisher_ID, remote_ip = Remote_IP, used_services = str:append(Modified_Used_Services, ["fbk"|""])};
{error, Response} ->
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "fbk", Login, true}),
State
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "fbk"}, {code, "103"}, {login, Login}], ["Error in IM Server Component"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {remove_im, "fbk", Login, true}),
State
end;
"wim" ->
case find_login_host([], Login) of
{"", _Domain} ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Username"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
{_User, ""} ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Domain"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
{User, Domain} ->
case im_messenger:start(?WIM_SERVER, Domain, ?JABBER_RESOURCE, self(), State#im_session_state.box_pid, State#im_session_state.session_id, Encoding) of
{ok, PID} ->
Conn_Map = dict:store("wim", PID, Modified_Connection_Map),
case gen_server:call(PID, {connect, lists:flatten(User), Decrypted_Password}, 60000) of
{ok, Message} ->
gen_server:cast(self(), {send_response, Message, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, {start_authenticating}),
State#im_session_state{connection_map = Conn_Map, publisher_id = Publisher_ID, remote_ip = Remote_IP, used_services = str:append(Modified_Used_Services, ["wim"|""])};
{fail, Message} ->
gen_server:cast(self(), {send_response, Message, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "wim", Login, true}),
State;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "wim"}, {code, "108"}, {login, Login}], ["Server Connection Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "wim", Login, true}),
State
end;
_Error ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "wim"}, {code, "103"}, {login, Login}], ["Error in IM Server Component"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {remove_im, "wim", Login, true}),
State
end
end;
"jab" ->
case find_login_host([], Login) of
{"", _Domain} ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Username"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
{_User, ""} ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Domain"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
{User, Domain} ->
case im_jabber:start(?GTALK_SERVER, Domain, ?JABBER_RESOURCE, self()) of
{ok, PID} ->
Conn_Map = dict:store("jab", PID, Modified_Connection_Map),
case gen_server:call(PID, {connect, lists:flatten(User), Decrypted_Password}, 60000) of
{ok, Message} ->
gen_server:cast(self(), {send_response, Message, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, {start_authenticating}),
State#im_session_state{connection_map = Conn_Map, publisher_id = Publisher_ID, remote_ip = Remote_IP, used_services = str:append(Modified_Used_Services, ["jab"|""])};
{fail, Message} ->
gen_server:cast(self(), {send_response, Message, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "jab", Login, true}),
State;
_ ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "jab"}, {code, "108"}, {login, Login}], ["Server Connection Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(PID, kill_connection),
gen_server:cast(self(), {remove_im, "jab", Login, true}),
State
end;
_Error ->
Response = [{response, [{type, "error"}, {errtype, "fatal"}, {im, "jab"}, {code, "103"}, {login, Login}], ["Error in IM Server Component"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {remove_im, "jab", Login, true}),
State
end
end
end;
process_request([{login, {login, _, _, _, _, _}}], Client_Record, Send_Socket, Socket_Type, State) ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["This Service Not Handled"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the poll XML request
%%% Usage - process_request(#request(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{request, {request, [Type], [Box_No], _}}], Client_Record, Send_Socket, Socket_Type, State) when Type == "" orelse Box_No == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameter"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{request, {request, ["poll"], Box_No, _}}], Client_Record, Send_Socket, Socket_Type, State) ->
#client_request{encoding = Encoding, connection_type = Connection_Type, callback = Handler, debug = Debug} = Client_Record,
?PRINT("Handling Poll Request ~n", []),
#im_session_state{handle_packet_pid = Handle_Packet_PID} = State,
gen_server:cast(self(), {add_box_message_request, Send_Socket, list_to_integer(lists:flatten(Box_No)), Encoding, Socket_Type, Connection_Type, Handle_Packet_PID, Handler, Debug}),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the typing XML request.
%%% Usage - process_request(#typing(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{typing, {typing, [IM_Type], [Login], [Buddy_Name], [Type]}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" orelse Login == "" orelse Buddy_Name == "" orelse Type == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameter"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{typing, {typing, IM, _, Buddy_Name, Type}}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{connection_map = Connection_Map} = State,
Name = xmerl_ucs:to_utf8(lists:flatten(Buddy_Name)),
Service = lists:flatten(IM),
case dict:find(Service, Connection_Map) of
{ok, PID} ->
gen_server:cast(PID, {send_typing_indication, lists:flatten(Name), lists:flatten(Type)}),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
error ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Typing indication send failure"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end,
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the message XML request.
%%% Usage - process_request(#message(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{message, {message, [IM_Type], [Login], [Buddy_Name], _}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" orelse Login == "" orelse Buddy_Name == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{message, {message, IM, _, Buddy_Name, Msg}}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{connection_map = Connection_Map} = State,
Service = lists:flatten(IM),
Name = xmerl_ucs:to_utf8(lists:flatten(Buddy_Name)),
A = lists:flatten(Msg),
if
length(A) >= 38 ->
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
Message = str:append(B, lists:sublist(A, 39, length(A)));
true ->
Message = A
end,
case dict:find(Service, Connection_Map) of
{ok, PID} ->
gen_server:cast(PID, {send_message, Name, ?MSG_CHAT, Message}),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
error ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Message Send Failure"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end,
State;
process_request([{fbk_fun, {fbk_fun, [IM_Type], [Login], _, [Type]}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" orelse Login == "" orelse Type == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{fbk_fun, {fbk_fun, [IM_Type], _, [Buddy_Name], [Type]}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "fbk" ->
#im_session_state{connection_map = Connection_Map} = State,
case dict:find(IM_Type, Connection_Map) of
{ok, PID} ->
case Type of
"notification" ->
gen_server:cast(PID, get_notification),
Response = [{response, [{type, "success"}], []}];
"livefeed" ->
gen_server:cast(PID, get_livefeed),
Response = [{response, [{type, "success"}], []}];
"inbox" ->
gen_server:cast(PID, get_mails),
Response = [{response, [{type, "success"}], []}];
"wallfeed" ->
gen_server:cast(PID, {get_wall_feeds, Buddy_Name}),
Response = [{response, [{type, "success"}], []}];
"chathistory" ->
gen_server:cast(PID, {get_chat_history, Buddy_Name}),
Response = [{response, [{type, "success"}], []}];
"poke" ->
if
Buddy_Name /= "" ->
gen_server:cast(PID, {send_poke, Buddy_Name}),
Response = [{response, [{type, "success"}], []}];
true ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Poke Send Failure"]}]
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Unknown Message Type"]}]
end,
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
error ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Message Send Failure"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end,
State;
%begin conference
%Handling Conference Record
% check the semantics of conf records
% add the conference record if required
% seperate the record using service and send them to their corresponding service pids
%[{conference_message,["lakshmi@hotmail.com"],["msn"],["lakshmi123"],["message"],["Hello are u parsing it well...so on"]}]
process_request([{conference, {conference, [IM_Type], [Login], [Conf_ID], [Code], _, _}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" orelse Login == "" orelse Conf_ID == "" orelse Code == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{conference, [HostName], [HostService], [ConfId], ["message"], Msg}], Client_Record, Send_Socket, Socket_Type, State) ->
%% find the conference details and cast the message to all service pids
A = lists:flatten(Msg),
if
length(A) >= 38 ->
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
Message = str:append(B, lists:sublist(A, 39, length(A)));
true ->
Message = A
end,
case lists:keysearch(ConfId,1,State#im_session_state.conference_details_list) of
{value,{ConferenceId,HostName,HostService,ServicesList}} ->
io:format("...............process_request() - ~n~p~n",[{ConferenceId,HostName,HostService,ServicesList}]),
Response = [{response, [{type, "success"}], []}],
cast_message_to_all_services(ServicesList, ConferenceId, Message, Client_Record, Send_Socket, Socket_Type, State);
%%({conference,[IM],[Login],[ConferenceID],[Operation],Message,BuddyList}
false ->
Response = [{response, [{type, "error"}, {errtype, "nonfatal"}], ["No Conference exists with this Id"]}]
end,
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{conference, [HostName], [HostService], [ConfId], [Operation], ConfServiceDetails}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{connection_map = Connection_Map} = State,
case Operation of
"initiate" ->
io:format("im_session: into Iniate conference clause ConfServiceDetails = ~p ~n",[ConfServiceDetails]),
%% Generate conference Id, add conf_details = [{id,hostname,hostservice,servicesList}],
%% Cast this information to all services existing in serviceList
ConferenceId = State#im_session_state.conference_id + 1,
%% NewConferenceId = "conference" ++ integer_to_list(ConferenceId),
NewConferenceId = string:sub_string(os:cmd("uuid -F STR"),1,36),
ServicesList = cast_initiate_request_to_all_service_pids(ConfServiceDetails,NewConferenceId, Client_Record,Send_Socket,Socket_Type,State),
io:format("im_session: sent request to all the services ~n"),
Conference_Details_List = State#im_session_state.conference_details_list,
NewConference_Details_List = [{NewConferenceId,HostName,HostService,ServicesList} | Conference_Details_List],
Response = [{response, [{type, "success"}], []}],
NewStateData= State#im_session_state{conference_id=ConferenceId,conference_details_list=NewConference_Details_List};
"invite" ->
io:format("im_session: into Invite conference clause ConfServiceDetails= ~p ~n",[ConfServiceDetails]),
case lists:keysearch(ConfId,1,State#im_session_state.conference_details_list) of
{value,{NewConferenceId,NewHostName,NewHostService,ServicesList}} ->
NewServicesList = cast_invite_request_to_all_service_pids(ConfServiceDetails,NewConferenceId,ServicesList, Client_Record,Send_Socket,Socket_Type,State),
ConfServiceDetailsList = State#im_session_state.conference_details_list,
Temp = lists:delete({NewConferenceId,NewHostName,NewHostService,ServicesList},ConfServiceDetailsList),
NewConference_Details_List = [{NewConferenceId,NewHostName,NewHostService,NewServicesList} | Temp],
Response = [{response, [{type, "success"}], []}],
NewStateData = State#im_session_state{conference_details_list = NewConference_Details_List};
false ->
if length(ConfId) == 36 ->
Response = [{response, [{type, "success"}], []}],
ServicesList = cast_initiate_request_to_all_service_pids(ConfServiceDetails, ConfId, Client_Record,Send_Socket,Socket_Type,State),
NewConference_Details_List = [{ConfId, HostName, HostService, ServicesList} | State#im_session_state.conference_details_list],
NewStateData = State#im_session_state{conference_details_list = NewConference_Details_List};
true ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference: No such conf exists"]}],
NewStateData = State
end
end;
"leaveeeeeeeeeeeeee" ->%or exit?
io:format("im_session: Entering into conference leave clause ConfServiceDetails = ~p ~n",[ConfServiceDetails]),
case lists:keysearch(ConfId,1,State#im_session_state.conference_details_list) of
{value,{NewConferenceId,NewHostName,NewHostService,ServicesList}} ->
ConfServiceDetailsList = State#im_session_state.conference_details_list,
Temp = lists:delete({NewConferenceId,NewHostName,NewHostService,ServicesList},ConfServiceDetailsList),
Length = lists:flatlength(ConfServiceDetails),
if
Length == 1 ->
[{[ConfDService],[_ConfDServiceLogin],_ConfDList}] = ConfServiceDetails,
io:format("entered if clause Length = 1 ConfDService = ~p ~n ServicesList = ~p ~n",[ConfDService, ServicesList]),
case lists:keysearch(ConfDService,1,ServicesList) of
{value,{ServiceID,ServiceLogin,Count,Members}} ->
io:format("cast to the remaining services saying Members of a Service are leaving the conference ~n"),
case dict:find(ServiceID, Connection_Map) of
{ok,Service_PID} ->
gen_server:cast(Service_PID,{conference,[ServiceID],[ServiceLogin],[NewConferenceId],["leave"],[],Members});
_->
io:format(" leave clause 000 ~n"),
nothing
end,
case lists:delete({ServiceID,ServiceLogin,Count,Members},ServicesList) of
[] ->
NewConference_Details_List = Temp;
NewServicesList ->
NewConference_Details_List = [{NewConferenceId,HostName,HostService,NewServicesList} | Temp],
%% cast the leave messge to remaining service buddies in conference
TempMessage1 = io_lib:format(">All the following ~s buddies left conference/conversation...~p ",[NewHostService,Members]),
TempMessage2 = ["<font color=","\"#000000","\"",TempMessage1,"</font",">"],
A = lists:flatten(TempMessage2),
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
LeaveMessage = str:append(B, lists:sublist(A, 39, length(A))),
cast_message_to_all_services(NewServicesList,ConfId,LeaveMessage, Client_Record, Send_Socket, Socket_Type, State)
end,
NewStateData = State#im_session_state{conference_details_list = NewConference_Details_List},
Response = [{response, [{type, "success"}], []}];
false ->
io:format(" leave clause 111 ~n"),
NewStateData = State,
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference " ++ ConfId ++ " does not have this " ++ ConfDService ++ " service buddies"]}]
end;
true ->% ifs else part
io:format(" leave clause 222 ~n"),
NewStateData = State,
Response = [{response, [{type, "error"}, {errtype, "client"}], ["More than one service in leave op"]}]
end;
false ->
NewStateData = State,
Response = [{response, [{type, "error"}, {errtype, "client"}], ["No conference exists with this ID"]}]
end;
"leave" -> %"exit" ->
io:format("im_session: cast leave message to all the services in that conference ~n"),
ConfServiceDetailsList = State#im_session_state.conference_details_list,
case lists:keysearch(ConfId, 1, ConfServiceDetailsList) of
{value,{NewConferenceId,HostName,HostService,ServicesList}} ->
cast_leave_operation_to_all_services(ServicesList,NewConferenceId,Connection_Map),
Temp = lists:delete({NewConferenceId,HostName,HostService,ServicesList},ConfServiceDetailsList),
NewStateData = State#im_session_state{conference_details_list = Temp},
Response = [{response, [{type, "success"}], []}];
false ->
NewStateData = State,
Response = [{response, [{type, "error"}, {errtype, "client"}], ["No Such conference exists to Close"]}]
end;
"accept" ->
io:format("im_session: Entering into conference accept clause ConfServiceDetails = ~p ~n",[ConfServiceDetails]),
case dict:find(HostService,Connection_Map) of
{ok,Service_PID} ->
case ConfServiceDetails of
[{_IM,_Login,BuddyList}] ->
Response = [{response, [{type, "success"}], []}],
gen_server:cast(Service_PID,{conference,[HostService],[HostName],[ConfId],[Operation],[],BuddyList}),
%% add the conf record in conference_details_list
Temp = State#im_session_state.conference_details_list,
NewConference_Details_List = [{ConfId,HostName,HostService,[{HostService,HostName,0,[]}]} | Temp],
NewStateData = State#im_session_state{conference_details_list=NewConference_Details_List};
_->
NewStateData = State,
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference: syntax error"]}]
end;
error ->
NewStateData = State,
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Service " ++ HostService ++ " is not logged in"]}]
end;
"reject" ->
io:format("im_session: Entered into conference reject clause ~n"),
case dict:find(HostService,Connection_Map) of
{ok,Service_PID} ->
case ConfServiceDetails of
[{_IM,_Login,BuddyList}] ->
Response = [{response, [{type, "success"}], []}],
gen_server:cast(Service_PID,{conference,[HostService],[HostName],[ConfId],[Operation],[],BuddyList});
_->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference: syntax error"]}]
end;
error ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Service " ++ HostService ++ " is not logged in"]}]
end,
NewStateData = State;
_->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Unknown CONF Operation"]}],
NewStateData = State
end,
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
NewStateData;
process_request([{conference, {conference, IM, Login, ConferenceID, ["initiate"], Msg, BuddyList}}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{connection_map = Connection_Map} = State,
Service = lists:flatten(IM),
%Name = xmerl_ucs:to_utf8(lists:flatten(Buddy_Name)),
A = lists:flatten(Msg),
if
length(A) >= 38 ->
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
Message = str:append(B, lists:sublist(A, 39, length(A)));
true ->
Message = A
end,
Message,
case dict:find(Service, Connection_Map) of
{ok,Service_PID} ->
gen_server:cast(Service_PID,{conference, IM, Login, ConferenceID, ["initiate"], Message, BuddyList}),
?PRINT("im_session: initiate conference packet Sending Conference Packet to corresponding service buddy ~n", []),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
_->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference: Communication Failure"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end,
State;
process_request([{conference, {conference, IM, Login, ConferenceID, Operation, Msg, BuddyList}}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{connection_map = Connection_Map} = State,
Service = lists:flatten(IM),
%%Name = xmerl_ucs:to_utf8(lists:flatten(Buddy_Name)),
A = lists:flatten(Msg),
if
length(A) >= 38 ->
B = element(2, regexp:gsub(lists:sublist(A, 1, 38), """, "'")),
Message = str:append(B, lists:sublist(A, 39, length(A)));
true ->
Message = A
end,
Message,
?PRINT("Sending Conference Packet to corresponding service buddy ~n", []),
case dict:find(Service, Connection_Map) of
{ok,Service_PID} ->
gen_server:cast(Service_PID,{conference, IM, Login, ConferenceID, Operation, Message, BuddyList}),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
_->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference: Communication Failure"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end,
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the status XML request.
%%% Usage - process_request(#message(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{status, {status, [Code], [Message]}}], Client_Record, Send_Socket, Socket_Type, State) when Code == "" orelse Message == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{status, {status, Code, Message}}], Client_Record, Send_Socket, Socket_Type, State) ->
gen_server:cast(self(), {set_status, list_to_integer(lists:flatten(Code)), lists:flatten(Message)}),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the friendship XML request which allows to add, remove
%%% and block a contact.
%%% Usage - process_request(#message(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{friendship, {friendship, [IM_Type], [Login], [Name], _, [Type], _}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" orelse Login == "" orelse Name == "" orelse Type == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{friendship, {friendship, IM, Login, Name, [""], Type, Message}}], Client_Record, Send_Socket, Socket_Type, State) ->
handle_friendship(lists:flatten(IM), lists:flatten(Login), lists:flatten(Name), "Friends", lists:flatten(Type), lists:flatten(Message), Client_Record, Send_Socket, Socket_Type, State),
State;
process_request([{friendship, {friendship, IM, Login, Name, Group, Type, Message}}], Client_Record, Send_Socket, Socket_Type, State) ->
handle_friendship(lists:flatten(IM), lists:flatten(Login), lists:flatten(Name), lists:flatten(Group), lists:flatten(Type), lists:flatten(Message), Client_Record, Send_Socket, Socket_Type, State),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the group XML request which is used to rename, remove
%%% and add a group. Also it allows to move a contact from one group to another.
%%% Usage - process_request(#message(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{group, {group, [IM_Type], [Login], _, _, _}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" orelse Login == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{group, {group, IM, _Login, _Type, _Old_Group_Name, _Contact, _New_Group_Name}}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{connection_map = Connection_Map, used_services = Used_Services} = State,
Type = lists:flatten(_Type),
Contact = xmerl_ucs:to_utf8(lists:flatten(_Contact)),
Old_Group_Name = xmerl_ucs:to_utf8(lists:flatten(_Old_Group_Name)),
New_Group_Name = xmerl_ucs:to_utf8(lists:flatten(_New_Group_Name)),
Service = lists:flatten(IM),
case Type of
"rename" ->
rename_group(Used_Services, Connection_Map, Old_Group_Name, New_Group_Name),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
"remove" ->
remove_group(Used_Services, Connection_Map, Old_Group_Name),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
"add" ->
case dict:find(Service, Connection_Map) of
{ok, IM_PID} ->
gen_server:cast(IM_PID, {add_group, Old_Group_Name}),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
error ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Add Group Request Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end;
"movecontact" ->
case dict:find(Service, Connection_Map) of
{ok, IM_PID} ->
gen_server:cast(IM_PID, {move_contact, Contact, Old_Group_Name, New_Group_Name}),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record});
error ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Move Contact Request Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Group Request Failed"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end,
State;
process_request([{file, {file, [IM_Type], [Login], [Name], [File_Name], _, _, [Type]}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" orelse Login == "" orelse Name == "" orelse File_Name == "" orelse Type == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{file, {file, IM, _Login, Name, _File_Name, _, _Key, _Type}}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{config_record = Config_Record, connection_map = Connection_Map} = State,
#config_record{file_send_directory = File_Send_Directory, file_receive_directory = File_Receive_Directory} = Config_Record,
Service = lists:flatten(IM),
Buddy_Name = xmerl_ucs:to_utf8(lists:flatten(Name)),
File_Name = lists:flatten(_File_Name),
Type = lists:flatten(_Type),
Key = lists:flatten(_Key),
case dict:find(Service, Connection_Map) of
{ok, IM_PID} ->
case Type of
"send" ->
io:format("im_session: cast {send_file, ~s, ~s, ~s, ~s }~n ~n",[Buddy_Name,File_Send_Directory,File_Name,key]),
gen_server:cast(IM_PID, {send_file, Buddy_Name, File_Send_Directory, File_Name,Key}),%no need for Key
Response = [{response, [{type, "success"}], []}];
"accept" ->
gen_server:cast(IM_PID, {accept_file, Buddy_Name, File_Receive_Directory, File_Name, Key}),
Response = [{response, [{type, "success"}], []}];
"deny" ->
gen_server:cast(IM_PID,{deny_file, Buddy_Name, File_Receive_Directory, File_Name, Key}),
Response = [{response, [{type, "success"}], []}];
_ ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["File Transfer Failed"]}]
end;
error ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["File Transfer Failed"]}]
end,
gen_server:cast(self(),{send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the referral XML request.
%%% Usage - process_request(#message(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{referral, {referral, [Refer_URL], [URLToBeSent], [Customer], [Private], [{message, Message} | Buddies ]}}], Client_Record, Send_Socket, Socket_Type, State) ->
#client_request{publisher_id = Publisher_ID, remote_host = Remote_Host, remote_ip = Remote_IP, referer = Referer} = Client_Record,
Progress_Rate = 100 / length(Buddies),
Response = [{referral, [{progress, "0"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
gen_server:cast(self(), {send_referral, Buddies, Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer}),
State#im_session_state{progress = 0, progress_rate = Progress_Rate};
%%%----------------------------------------------------------------------------------------------------
%%% Description - This method is used to process the logout XML request.
%%% Usage - process_request(#message(), string(), string(), string(), string(), string(), integer(), socket(), atom(), string(), #im_session_state())
%%%----------------------------------------------------------------------------------------------------
process_request([{logout, {logout, [IM_Type], _}}], Client_Record, Send_Socket, Socket_Type, State) when IM_Type == "" ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Missing Parameters"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State;
process_request([{logout, {logout, IM, Login_Name}}], Client_Record, Send_Socket, Socket_Type, State) ->
#im_session_state{connection_map = Connection_Map, used_services = Used_Services} = State,
Service = lists:flatten(IM),
Login = xmerl_ucs:to_utf8(lists:flatten(Login_Name)),
Response = [{response, [{type, "success"}], []}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
if
Service == "all" ->
handle_logout(Used_Services, "", Connection_Map),
State;
true ->
handle_logout([Service|""], Login, Connection_Map),
NewConference_Details_List = handle_conference_logout(Service, State#im_session_state.conference_details_list),
State#im_session_state{conference_details_list = NewConference_Details_List}
end;
process_request(_, Client_Record, Send_Socket, Socket_Type, State) ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Invalid Message"]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
State.
handle_logout([], _, _) ->
nothing;
handle_logout([IM_Type|B], Login, Connection_Map) ->
if
IM_Type == "yah" orelse IM_Type == "aim" orelse IM_Type == "icq" orelse IM_Type == "fbk" ->
case dict:find(IM_Type, Connection_Map) of
{ok, PID} ->
gen_server:call(PID, logout, infinity);
error ->
nothing
end,
gen_server:cast(self(), {remove_im, IM_Type, Login, false});
IM_Type == "jab" orelse IM_Type == "wim" ->
case dict:find(IM_Type, Connection_Map) of
{ok, PID} ->
gen_server:cast(PID, logout);
error ->
nothing
end,
gen_server:cast(self(), {remove_im, IM_Type, Login, false});
IM_Type == "msn" ->
case dict:find(IM_Type, Connection_Map) of
{ok, PID} ->
gen_server:cast(PID, disconnect);
error ->
nothing
end,
gen_server:cast(self(), {remove_im, "msn", Login, false});
true ->
nothing
end,
handle_logout(B, Login, Connection_Map).
handle_friendship(Service, _, Buddy_Name, Group_Name, Type, Message, Client_Record, Send_Socket, Socket_Type, State) ->
?PRINT("Inside Handle Friendship ~n", []),
#im_session_state{connection_map = Connection_Map} = State,
Group = xmerl_ucs:to_utf8(Group_Name),
Name = xmerl_ucs:to_utf8(Buddy_Name),
case dict:find(Service, Connection_Map) of
{ok, PID} ->
case Type of
"remove" ->
gen_server:cast(PID, {remove_buddy, Name, Group}),
Response = [{response, [{type, "success"}], []}];
"block" ->
gen_server:cast(PID, {block_buddy, Name, Group}),
Response = [{response, [{type, "success"}], []}];
"unblock" ->
gen_server:cast(PID, {unblock_buddy, Name}),
Response = [{response, [{type, "success"}], []}];
"authorize" ->
gen_server:cast(PID, {authorize_buddy_request, Name, Group}),
Response = [{response, [{type, "success"}], []}];
"deny" ->
gen_server:cast(PID, {deny_buddy_request, Name}),
Response = [{response, [{type, "success"}], []}];
"add" ->
if
Service == "yah" ->
Return = gen_server:call(PID, {check_block_list, {Name}}, infinity),
if
Return == false ->
gen_server:cast(PID, {add_buddy, Name, Group, Message, true}),
Response = [{response, [{type, "success"}], []}];
true ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Frienship Request Failure"]}]
end;
Service == "msn" orelse Service == "jab" ->
gen_server:cast(PID, {add_buddy, Name, Group}),
Response = [{response, [{type, "success"}], []}];
Service == "aim" orelse Service == "icq" ->
Return = gen_server:call(PID, {check_block_list, Name}, infinity),
if
Return == false ->
gen_server:cast(PID, {add_buddy, Name, Group}),
Response = [{response, [{type, "success"}], []}];
true ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Frienship Request Failure"]}]
end;
true ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Frienship Request Failure"]}]
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Frienship Request Failure"]}]
end;
_ ->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Frienship Request Failure"]}]
end,
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}).
find_login_host(A, []) ->
{A, ""};
find_login_host(A, [B|C]) ->
if
B == "@" orelse B == 64 ->
{A, C};
true ->
D = [B|""],
find_login_host(str:append(A, D), C)
end.
send_referral({buddies, [Service], [From], [To]}, MessageList, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, _, Referer) ->
[LastMessage | TailMessage] = lists:reverse(MessageList),
{N1, N2, N3} = now(),
Ticket = integer_to_list(N1) ++ integer_to_list(N2) ++ integer_to_list(N3),
ReferralMesg = io_lib:format("~s%0A~s", [LastMessage, URLToBeSent ++ Ticket]),
case Service of
"jab"->
Msg = lists:flatten(["<font color='#000000'>", lists:reverse(TailMessage), ReferralMesg, "</font>"]);
"msn" ->
Msg = lists:flatten(["<font color='#000000'>", lists:reverse(TailMessage), ReferralMesg, "</font>"]);
_ ->
Msg = lists:flatten([lists:reverse(TailMessage), ReferralMesg])
end,
Query = io_lib:format("call add_referral('~s', '~s', '~s', '~s', '~s', '~s', '~s', '~s', '~s', '~s');", [Ticket, Customer, Remote_IP, Remote_Host, From, To, Service, Refer_URL, Private, Referer]),
case gen_event:call(db_manager, db_referral, {add_referral, Query}, infinity) of
ok ->
{ok, Msg};
_ ->
error
end;
send_referral(_, _, _, _, _, _, _, _, _, _) ->
"<font color='#000000'></font>".
%% Intermediate Function for Timer
call_cast(Request, BuddyTail, Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer, ProcessID) ->
gen_server:cast(ProcessID, {Request, BuddyTail, Message, URLToBeSent, Customer, Remote_IP, Remote_Host, Refer_URL, Private, Publisher_ID, Referer}).
%----------------------------------------------------------------------------------------------------
% Description - This method is used to determine whether a string is in unicode format.
%----------------------------------------------------------------------------------------------------
is_unicode([]) ->
false;
is_unicode([A|B]) ->
if
A > 255 ->
true;
true ->
is_unicode(B)
end.
rename_group([], _, _, _) ->
ok;
rename_group([A|B], Connection_Map, Old_Group_Name, New_Group_Name) ->
case dict:find(A, Connection_Map) of
{ok, IM_PID} ->
gen_server:cast(IM_PID, {rename_group, Old_Group_Name, New_Group_Name});
error ->
nothing
end,
rename_group(B, Connection_Map, Old_Group_Name, New_Group_Name).
remove_group([], _, _) ->
ok;
remove_group([A|B], Connection_Map, Group_Name) ->
case dict:find(A, Connection_Map) of
{ok, IM_PID} ->
gen_server:cast(IM_PID, {remove_group, Group_Name});
error ->
nothing
end,
remove_group(B, Connection_Map, Group_Name).
get_contacts([], _, _) ->
ok;
get_contacts([A|B], Connection_Map, Addr_Book_URL) ->
case dict:find(A, Connection_Map) of
{ok, IM_PID} ->
gen_server:cast(IM_PID, {get_contacts, Addr_Book_URL});
error ->
nothing
end,
get_contacts(B, Connection_Map, Addr_Book_URL).
kill_child_process(State) ->
#im_session_state{session_id = Session_ID, connection_map = Connection_Map, used_services = Used_Services, remote_ip = Remote_IP, publisher_id = Publisher_ID} = State,
if
length(Used_Services) == 0 ->
nothing;
true ->
[IM_Type|_] = Used_Services,
case dict:find(IM_Type, Connection_Map) of
{ok, IM_PID} ->
gen_server:call(IM_PID, {add_update_db, Remote_IP, Publisher_ID, "0", Session_ID}, infinity),
New_Connection_Map = dict:erase(IM_Type, Connection_Map),
New_Used_Services = lists:delete(IM_Type, Used_Services),
gen_server:cast(IM_PID, kill_connection);
error ->
New_Connection_Map = Connection_Map,
New_Used_Services = lists:delete(IM_Type, Used_Services)
end,
kill_child_process(State#im_session_state{connection_map = New_Connection_Map, used_services = New_Used_Services})
end.
commit_suicide(State) ->
#im_session_state{session_id = Session_ID, connection_map = Connection_Map, used_services = Used_Services, remote_ip = Remote_IP, publisher_id = Publisher_ID} = State,
if
length(Used_Services) == 0 ->
gen_server:cast(self(), {commit_suicide, State});
true ->
[IM_Type|_] = Used_Services,
case dict:find(IM_Type, Connection_Map) of
{ok, IM_PID} ->
gen_server:call(IM_PID, {add_update_db, Remote_IP, Publisher_ID, "0", Session_ID}, infinity),
New_Connection_Map = dict:erase(IM_Type, Connection_Map),
New_Used_Services = lists:delete(IM_Type, Used_Services),
gen_server:cast(IM_PID, kill_connection);
error ->
New_Connection_Map = Connection_Map,
New_Used_Services = lists:delete(IM_Type, Used_Services)
end,
commit_suicide(State#im_session_state{connection_map = New_Connection_Map, used_services = New_Used_Services})
end.
get_conference_details_list([]) ->
[];
get_conference_details_list([{ConferenceId, HostName, HostService, ServicesList} | Rest]) ->
ServicesString = get_conf_service_wide_list(ServicesList),
Conf_Details = [{conf, [{hostname, HostName}, {hostservice, HostService}, {id, ConferenceId}, {operation, "refresh"}], ServicesString}],
Conf_Details ++ get_conference_details_list(Rest).
get_conf_service_wide_list([])->
[];
get_conf_service_wide_list([ {Service, Login, _Count, BuddyList} | REST]) ->
BuddyListString = get_conf_buddy_list(Service, Login, BuddyList),
BuddyListString ++ get_conf_service_wide_list(REST).
get_conf_buddy_list(_Service, _Login, []) ->
[];
get_conf_buddy_list(Service, Login, [Buddy | Rest]) ->
String = [{conference, [{im, Service}, {login, Login}, {service, Service}, {name, Buddy}], []}],
String ++ get_conf_buddy_list(Service, Login, Rest).
cast_leave_operation_to_all_services([{Service,Login,_Count,_Members} | ServicesList],ConfId,Connection_Map) ->
case dict:find(Service,Connection_Map) of
{ok,Service_PID} ->
gen_server:cast(Service_PID,{conference,[Service],[Login],[ConfId],["leave"],[],[]});
error ->
io:format("im_session: %%%%%%%% Service PID is missing Is he logged out already ~n ")
end,
cast_leave_operation_to_all_services(ServicesList,ConfId,Connection_Map);
cast_leave_operation_to_all_services([],_ConfId,_Connection_Map) ->
ok.
cast_message_to_all_services([ Head | Rest], ConferenceId, Message, Client_Record, Send_Socket, Socket_Type, State) ->
{IM,IMLogin,Count,_BuddyList} = Head,
#im_session_state{connection_map = Connection_Map} = State,
if
Count > 0 ->
case dict:find(IM, Connection_Map) of
{ok,Service_PID} ->
io:format("im_session: Sending message packet to corresponding im_~s ~n", [IM]),
gen_server:cast(Service_PID,{conference,[IM],[IMLogin],[ConferenceId],["message"],Message,[]});
_->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference:" ++ IM ++ " Service not logged in "]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end;
true ->
ok
end,
cast_message_to_all_services(Rest,ConferenceId,Message, Client_Record,Send_Socket,Socket_Type,State);
cast_message_to_all_services([],_ConferenceId,_Message,_Config_Record, _Send_Socket, _Socket_Type, _State) ->
success.
cast_initiate_request_to_all_service_pids([ConfServiceDetails | Rest],NewConferenceId,Client_Record, Send_Socket,Socket_Type,State) ->
#im_session_state{connection_map = Connection_Map} = State,
{[IM],[Login],BuddyList} = ConfServiceDetails,
case dict:find(IM, Connection_Map) of
{ok,Service_PID} ->
gen_server:cast(Service_PID,{conference,[IM],[Login],[NewConferenceId],["initiate"],[],BuddyList}),
?PRINT("im_session: Sending initiate conference packet to corresponding service buddy ~n", []);
_->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference: No user logged in with this " ++ IM ++ " service "]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record})
end,
[{IM,Login,0,[]} | cast_initiate_request_to_all_service_pids(Rest,NewConferenceId, Client_Record,Send_Socket,Socket_Type,State)];
cast_initiate_request_to_all_service_pids([],_NewConferenceId,_Client_Recod,_Send_Socket,_Socket_Type,_State) ->
io:format("empty confdetails~n"),
[].
cast_invite_request_to_all_service_pids([ConfServiceDetails | Rest],NewConferenceId,ServicesList,Client_Record, Send_Socket,Socket_Type,State) ->
#im_session_state{connection_map = Connection_Map} = State,
{[IM],[Login],BuddyList} = ConfServiceDetails,
case dict:find(IM, Connection_Map) of
{ok,Service_PID} ->
gen_server:cast(Service_PID,{conference,[IM],[Login],[NewConferenceId],["invite"],[],BuddyList}),
case lists:keysearch(IM,1,ServicesList) of
{value,{_ServiceID,_ServiceLogin,_Count,_Members}} ->
NewServicesList = ServicesList;%{ServiceID,ServiceLogin,Count,Members};
false ->
NewServicesList = [{IM,Login,0,[]} | ServicesList]
end,
cast_invite_request_to_all_service_pids(Rest,NewConferenceId,NewServicesList,Client_Record, Send_Socket,Socket_Type,State);
_->
Response = [{response, [{type, "error"}, {errtype, "client"}], ["Conference: No user logged in with this " ++ IM ++ " service "]}],
gen_server:cast(self(), {send_response, Response, Send_Socket, Socket_Type, Client_Record}),
cast_invite_request_to_all_service_pids(Rest,NewConferenceId,ServicesList,Client_Record,Send_Socket,Socket_Type,State)
end;
cast_invite_request_to_all_service_pids([],_NewConferenceId,ServicesList,_Client_Record,_Send_Socket,_Socket_Type,_State) ->
ServicesList.
cast_join_leave_message_to_other_services([First | ServicesList],IM_Type,LoginName,ConferenceId,Message,Connection_Map) ->
{IM,Login,Count,_Members} = First,
case dict:find(IM,Connection_Map) of
{ok,ServicePid} ->
if
IM /= IM_Type andalso Count > 0 ->
gen_server:cast(ServicePid,{conference,[IM],[Login],[ConferenceId],["message"],Message,[]});
true ->
nothing
end;
error ->
nothing
end,
cast_join_leave_message_to_other_services(ServicesList,IM_Type,LoginName,ConferenceId,Message,Connection_Map);
cast_join_leave_message_to_other_services([],_IM_Type,_LoginName,_ConferenceId,_Message,_Connection_Map) ->
ok.
handle_conference_logout(_ServiceType, []) ->
[];
handle_conference_logout(ServiceType, [ ConfDetails | Conference_Details_List]) ->
io:format("########### ~nhandle_conference_logout() ~n~p~n###########~n",[ConfDetails]),
{ConferenceId, HostName, HostService, ServicesList} = ConfDetails,
case lists:keysearch(ServiceType, 1, ServicesList) of
{value, ServiceDetails} ->
case lists:delete(ServiceDetails, ServicesList) of
[] ->
handle_conference_logout(ServiceType, Conference_Details_List);
NewServicesList ->
[{ConferenceId,HostName,HostService,NewServicesList} | handle_conference_logout(ServiceType, Conference_Details_List) ]
end;
_->
[ ConfDetails | handle_conference_logout(ServiceType, Conference_Details_List)]
end.
get_raw_message([{raw,Message} | Rest]) ->
[Message,get_raw_message(Rest)];
get_raw_message([])->
[];
get_raw_message([_Head | Rest])->
get_raw_message(Rest).