UserServer.pm 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package OpenSim::UserServer;
  2. use strict;
  3. use OpenSim::Config;
  4. use OpenSim::UserServer::Config;
  5. use OpenSim::UserServer::UserManager;
  6. sub getHandlerList {
  7. my %list = (
  8. "login_to_simulator" => \&_login_to_simulator,
  9. "get_user_by_name" => \&_get_user_by_name,
  10. "get_user_by_uuid" => \&_get_user_by_uuid,
  11. "get_avatar_picker_avatar" => \&_get_avatar_picker_avatar,
  12. );
  13. return \%list;
  14. }
  15. # #################
  16. # Handlers
  17. sub _login_to_simulator {
  18. my $params = shift;
  19. # check params
  20. if (!$params->{first} || !$params->{last} || !$params->{passwd}) {
  21. return &_make_false_response("not enough params", $OpenSim::Config::SYS_MSG{FATAL});
  22. }
  23. # select user (check passwd)
  24. my $user = &OpenSim::UserServer::UserManager::getUserByName($params->{first}, $params->{last});
  25. if ($user->{passwordHash} ne $params->{passwd}) {
  26. &_make_false_response("password not match", $OpenSim::Config::SYS_MSG{FAIL});
  27. }
  28. # contact with Grid server
  29. my %grid_request_params = (
  30. region_handle => $user->{homeRegion},
  31. authkey => undef
  32. );
  33. my $grid_response = &OpenSim::Utility::XMLRPCCall($OpenSim::Config::GRID_SERVER_URL, "simulator_data_request", \%grid_request_params);
  34. my $region_server_url = "http://" . $grid_response->{sim_ip} . ":" . $grid_response->{http_port};
  35. # contact with Region server
  36. my $session_id = &OpenSim::Utility::GenerateUUID;
  37. my $secure_session_id = &OpenSim::Utility::GenerateUUID;
  38. my $circuit_code = int(rand() * 1000000000); # just a random integer
  39. my $caps_id = &OpenSim::Utility::GenerateUUID;
  40. my %region_request_params = (
  41. session_id => $session_id,
  42. secure_session_id => $secure_session_id,
  43. firstname => $user->{username},
  44. lastname => $user->{lastname},
  45. agent_id => $user->{UUID},
  46. circuit_code => $circuit_code,
  47. startpos_x => $user->{homeLocationX},
  48. startpos_y => $user->{homeLocationY},
  49. startpos_z => $user->{homeLocationZ},
  50. regionhandle => $user->{homeRegion},
  51. caps_path => $caps_id,
  52. );
  53. my $region_response = &OpenSim::Utility::XMLRPCCall($region_server_url, "expect_user", \%region_request_params);
  54. # contact with Inventory server
  55. my $inventory_data = &_create_inventory_data($user->{UUID});
  56. # return to client
  57. my %response = (
  58. # login info
  59. login => "true",
  60. session_id => $session_id,
  61. secure_session_id => $secure_session_id,
  62. # agent
  63. first_name => $user->{username},
  64. last_name => $user->{lastname},
  65. agent_id => $user->{UUID},
  66. agent_access => "M", # TODO: do not know its meaning, hard coding in opensim
  67. # grid
  68. start_location => $params->{start},
  69. sim_ip => $grid_response->{sim_ip},
  70. sim_port => $grid_response->{sim_port},
  71. #sim_port => 9001,
  72. region_x => $grid_response->{region_locx} * 256,
  73. region_y => $grid_response->{region_locy} * 256,
  74. # other
  75. inventory_host => undef, # inv13-mysql
  76. circuit_code => $circuit_code,
  77. message => $OpenSim::Config::SYS_MSG{LOGIN_WELCOME},
  78. seconds_since_epoch => time,
  79. seed_capability => $region_server_url . "/CAPS/" . $caps_id . "0000/", # https://sim2734.agni.lindenlab.com:12043/cap/61d6d8a0-2098-7eb4-2989-76265d80e9b6
  80. look_at => &_make_r_string($user->{homeLookAtX}, $user->{homeLookAtY}, $user->{homeLookAtZ}),
  81. home => &_make_home_string(
  82. [$grid_response->{region_locx} * 256, $grid_response->{region_locy} * 256],
  83. [$user->{homeLocationX}, $user->{homeLocationY}, $user->{homeLocationX}],
  84. [$user->{homeLookAtX}, $user->{homeLookAtY}, $user->{homeLookAtZ}]),
  85. "inventory-skeleton" => $inventory_data->{InventoryArray},
  86. "inventory-root" => [ { folder_id => $inventory_data->{RootFolderID} } ],
  87. "event_notifications" => \@OpenSim::UserServer::Config::event_notifications,
  88. "event_categories" => \@OpenSim::UserServer::Config::event_categories,
  89. "global-textures" => \@OpenSim::UserServer::Config::global_textures,
  90. "inventory-lib-owner" => \@OpenSim::UserServer::Config::inventory_lib_owner,
  91. "inventory-skel-lib" => \@OpenSim::UserServer::Config::inventory_skel_lib, # hard coding in OpenSim
  92. "inventory-lib-root" => \@OpenSim::UserServer::Config::inventory_lib_root,
  93. "classified_categories" => \@OpenSim::UserServer::Config::classified_categories,
  94. "login-flags" => \@OpenSim::UserServer::Config::login_flags,
  95. "initial-outfit" => \@OpenSim::UserServer::Config::initial_outfit,
  96. "gestures" => \@OpenSim::UserServer::Config::gestures,
  97. "ui-config" => \@OpenSim::UserServer::Config::ui_config,
  98. );
  99. return \%response;
  100. }
  101. sub _get_user_by_name {
  102. my $param = shift;
  103. if ($param->{avatar_name}) {
  104. my ($first, $last) = split(/\s+/, $param->{avatar_name});
  105. my $user = &OpenSim::UserServer::UserManager::getUserByName($first, $last);
  106. if (!$user) {
  107. return &_unknown_user_response;
  108. }
  109. return &_convert_to_response($user);
  110. } else {
  111. return &_unknown_user_response;
  112. }
  113. }
  114. sub _get_user_by_uuid {
  115. my $param = shift;
  116. if ($param->{avatar_uuid}) {
  117. my $user = &OpenSim::UserServer::UserManager::getUserByUUID($param->{avatar_uuid});
  118. if (!$user) {
  119. return &_unknown_user_response;
  120. }
  121. return &_convert_to_response($user);
  122. } else {
  123. return &_unknown_user_response;
  124. }
  125. }
  126. sub _get_avatar_picker_avatar {
  127. }
  128. # #################
  129. # sub functions
  130. sub _create_inventory_data {
  131. my $user_id = shift;
  132. # TODO : too bad!! -> URI encoding
  133. my $postdata =<< "POSTDATA";
  134. POSTDATA=<?xml version="1.0" encoding="utf-8"?><guid>$user_id</guid>
  135. POSTDATA
  136. my $res = &OpenSim::Utility::HttpPostRequest($OpenSim::Config::INVENTORY_SERVER_URL . "/RootFolders/", $postdata);
  137. my $res_obj = &OpenSim::Utility::XML2Obj($res);
  138. if (!$res_obj->{InventoryFolderBase}) {
  139. &OpenSim::Utility::HttpPostRequest($OpenSim::Config::INVENTORY_SERVER_URL . "/CreateInventory/", $postdata);
  140. # Sleep(10000); # TODO: need not to do this
  141. $res = &OpenSim::Utility::HttpPostRequest($OpenSim::Config::INVENTORY_SERVER_URL . "/RootFolders/", $postdata);
  142. $res_obj = &OpenSim::Utility::XML2Obj($res);
  143. }
  144. my $folders = $res_obj->{InventoryFolderBase};
  145. my $folders_count = @$folders;
  146. if ($folders_count > 0) {
  147. my @AgentInventoryFolders = ();
  148. my $root_uuid = &OpenSim::Utility::ZeroUUID();
  149. foreach my $folder (@$folders) {
  150. if ($folder->{parentID}->{UUID} eq &OpenSim::Utility::ZeroUUID()) {
  151. $root_uuid = $folder->{folderID}->{UUID};
  152. }
  153. my %folder_hash = (
  154. name => $folder->{name},
  155. parent_id => $folder->{parentID}->{UUID},
  156. version => $folder->{version},
  157. type_default => $folder->{type},
  158. folder_id => $folder->{folderID}->{UUID},
  159. );
  160. push @AgentInventoryFolders, \%folder_hash;
  161. }
  162. return { InventoryArray => \@AgentInventoryFolders, RootFolderID => $root_uuid };
  163. } else {
  164. # TODO: impossible ???
  165. }
  166. return undef;
  167. }
  168. sub _convert_to_response {
  169. my $user = shift;
  170. my %response = (
  171. firstname => $user->{username},
  172. lastname => $user->{lastname},
  173. uuid => $user->{UUID},
  174. server_inventory => $user->{userInventoryURI},
  175. server_asset => $user->{userAssetURI},
  176. profile_about => $user->{profileAboutText},
  177. profile_firstlife_about => $user->{profileFirstText},
  178. profile_firstlife_image => $user->{profileFirstImage},
  179. profile_can_do => $user->{profileCanDoMask} || "0",
  180. profile_want_do => $user->{profileWantDoMask} || "0",
  181. profile_image => $user->{profileImage},
  182. profile_created => $user->{created},
  183. profile_lastlogin => $user->{lastLogin} || "0",
  184. home_coordinates_x => $user->{homeLocationX},
  185. home_coordinates_y => $user->{homeLocationY},
  186. home_coordinates_z => $user->{homeLocationZ},
  187. home_region => $user->{homeRegion} || 0,
  188. home_look_x => $user->{homeLookAtX},
  189. home_look_y => $user->{homeLookAtY},
  190. home_look_z => $user->{homeLookAtZ},
  191. );
  192. return \%response;
  193. }
  194. # #################
  195. # Utility Functions
  196. sub _make_false_response {
  197. my ($reason, $message) = @_;
  198. return { reason => $reason, login => "false", message => $message };
  199. }
  200. sub _unknown_user_response {
  201. return {
  202. error_type => "unknown_user",
  203. error_desc => "The user requested is not in the database",
  204. };
  205. }
  206. sub _make_home_string {
  207. my ($region_handle, $position, $look_at) = @_;
  208. my $region_handle_string = "'region_handle':" . &_make_r_string(@$region_handle);
  209. my $position_string = "'position':" . &_make_r_string(@$position);
  210. my $look_at_string = "'look_at':" . &_make_r_string(@$look_at);
  211. return "{" . $region_handle_string . ", " . $position_string . ", " . $look_at_string . "}";
  212. }
  213. sub _make_r_string {
  214. my @params = @_;
  215. foreach (@params) {
  216. $_ = "r" . $_;
  217. }
  218. return "[" . join(",", @params) . "]";
  219. }
  220. 1;