%%%---------------------------------------------------------------------------------------------------- %%% 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).