├── .github └── workflows │ └── go.yml ├── .gitignore ├── 7.5.0.201028 ├── idapro │ └── INSTALL_IDA_HERE ├── main_arm.idb ├── main_arm64.i64 ├── main_x86.idb └── main_x86_64.i64 ├── 7.6.0.210427 ├── idapro │ └── INSTALL_IDA_HERE ├── main_arm.idb ├── main_arm64.i64 ├── main_x86.idb └── main_x86_64.i64 ├── 7.7.0.220118 ├── idapro │ └── INSTALL_IDA_HERE ├── main_arm.idb ├── main_arm64.i64 ├── main_x86.idb └── main_x86_64.i64 ├── binary ├── main_arm ├── main_arm64 ├── main_x86 └── main_x86_64 ├── build.bat ├── go.mod ├── main.go ├── obpo_script.py └── process.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: [published] 7 | 8 | 9 | jobs: 10 | 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: Generate build files 17 | uses: thatisuday/go-cross-build@v1.1.0 18 | with: 19 | platforms: 'windows/amd64' 20 | name: 'obpo-server-${{ github.ref_name }}' 21 | dest: 'dist' 22 | - name: Release 23 | uses: softprops/action-gh-release@v0.1.14 24 | with: 25 | tag_name: ${{ github.ref_name }} 26 | files: dist/* 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /7.5.0.201028/idapro/* 2 | /7.6.0.210427/idapro/* 3 | /7.7.0.220118/idapro/* 4 | -------------------------------------------------------------------------------- /7.5.0.201028/idapro/INSTALL_IDA_HERE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.5.0.201028/idapro/INSTALL_IDA_HERE -------------------------------------------------------------------------------- /7.5.0.201028/main_arm.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.5.0.201028/main_arm.idb -------------------------------------------------------------------------------- /7.5.0.201028/main_arm64.i64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.5.0.201028/main_arm64.i64 -------------------------------------------------------------------------------- /7.5.0.201028/main_x86.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.5.0.201028/main_x86.idb -------------------------------------------------------------------------------- /7.5.0.201028/main_x86_64.i64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.5.0.201028/main_x86_64.i64 -------------------------------------------------------------------------------- /7.6.0.210427/idapro/INSTALL_IDA_HERE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.6.0.210427/idapro/INSTALL_IDA_HERE -------------------------------------------------------------------------------- /7.6.0.210427/main_arm.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.6.0.210427/main_arm.idb -------------------------------------------------------------------------------- /7.6.0.210427/main_arm64.i64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.6.0.210427/main_arm64.i64 -------------------------------------------------------------------------------- /7.6.0.210427/main_x86.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.6.0.210427/main_x86.idb -------------------------------------------------------------------------------- /7.6.0.210427/main_x86_64.i64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.6.0.210427/main_x86_64.i64 -------------------------------------------------------------------------------- /7.7.0.220118/idapro/INSTALL_IDA_HERE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.7.0.220118/idapro/INSTALL_IDA_HERE -------------------------------------------------------------------------------- /7.7.0.220118/main_arm.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.7.0.220118/main_arm.idb -------------------------------------------------------------------------------- /7.7.0.220118/main_arm64.i64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.7.0.220118/main_arm64.i64 -------------------------------------------------------------------------------- /7.7.0.220118/main_x86.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.7.0.220118/main_x86.idb -------------------------------------------------------------------------------- /7.7.0.220118/main_x86_64.i64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/7.7.0.220118/main_x86_64.i64 -------------------------------------------------------------------------------- /binary/main_arm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/binary/main_arm -------------------------------------------------------------------------------- /binary/main_arm64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/binary/main_arm64 -------------------------------------------------------------------------------- /binary/main_x86: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/binary/main_x86 -------------------------------------------------------------------------------- /binary/main_x86_64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obpo-project/obpo-server/b444c6cf088f2cc13d36b1d10263f769bedfde84/binary/main_x86_64 -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | set CGO_ENABLED=0 2 | set GOOS=windows 3 | set GOARCH=amd64 4 | go build -o ./dist/obpo_server_win64.exe . -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/obpo-project/obpo-server 2 | 3 | go 1.18 4 | 5 | require github.com/gin-gonic/gin v1.8.1 6 | 7 | require ( 8 | github.com/gin-contrib/sse v0.1.0 // indirect 9 | github.com/go-playground/locales v0.14.0 // indirect 10 | github.com/go-playground/universal-translator v0.18.0 // indirect 11 | github.com/go-playground/validator/v10 v10.10.0 // indirect 12 | github.com/goccy/go-json v0.9.7 // indirect 13 | github.com/json-iterator/go v1.1.12 // indirect 14 | github.com/leodido/go-urn v1.2.1 // indirect 15 | github.com/mattn/go-isatty v0.0.14 // indirect 16 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 17 | github.com/modern-go/reflect2 v1.0.2 // indirect 18 | github.com/pelletier/go-toml/v2 v2.0.1 // indirect 19 | github.com/ugorji/go/codec v1.2.7 // indirect 20 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect 21 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect 22 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect 23 | golang.org/x/text v0.3.6 // indirect 24 | google.golang.org/protobuf v1.28.0 // indirect 25 | gopkg.in/yaml.v2 v2.4.0 // indirect 26 | ) 27 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "github.com/gin-gonic/gin" 7 | "io/ioutil" 8 | "net/http" 9 | ) 10 | 11 | type ResultData struct { 12 | Mba string `json:"mba"` 13 | } 14 | 15 | type Response struct { 16 | Code int `json:"code"` 17 | Error string `json:"error"` 18 | Warn string `json:"warn"` 19 | Data ResultData `json:"data"` 20 | } 21 | 22 | func setupRouter() *gin.Engine { 23 | r := gin.Default() 24 | 25 | r.POST("/request", func(c *gin.Context) { 26 | request, _ := ioutil.ReadAll(c.Request.Body) 27 | response, err := json.Marshal(process(string(request))) 28 | if err != nil { 29 | c.String(http.StatusBadGateway, `{"code": 502}`) 30 | } else { 31 | c.String(http.StatusOK, string(response)) 32 | } 33 | }) 34 | return r 35 | } 36 | 37 | func listen() string { 38 | listen := ":10000" 39 | flag.StringVar(&listen, "l", ":10000", "listen address, default is :10000") 40 | flag.Parse() 41 | return listen 42 | } 43 | 44 | func main() { 45 | 46 | r := setupRouter() 47 | _ = r.Run(listen()) 48 | } 49 | -------------------------------------------------------------------------------- /obpo_script.py: -------------------------------------------------------------------------------- 1 | # Author: hluwa 2 | # HomePage: https://github.com/hluwa 3 | # CreateTime: 2022/3/8 4 | import base64 5 | import json 6 | import logging 7 | 8 | from idaapi import * 9 | from idc import * 10 | from obpo.analysis.dispatcher import DispatchAnalyzer 11 | from obpo.analysis.pathfinder import FlowFinder, EmuPathFinder 12 | from obpo.patch.deoptimizer import SplitCommonPatcher 13 | from obpo.patch.link import FlowPatcher 14 | 15 | TASK_PATH = ARGV[1] 16 | TASK_DIR = os.path.dirname(TASK_PATH) 17 | 18 | 19 | def _safe_call(f): 20 | try: 21 | return f() 22 | except: 23 | pass 24 | 25 | 26 | def warning(s): 27 | with open(os.path.join(TASK_DIR, "warn"), 'a') as o: 28 | o.write(s + "\r\n") 29 | 30 | 31 | def error(s): 32 | with open(os.path.join(TASK_DIR, "error"), 'a') as o: 33 | o.write(s + "\r\n") 34 | 35 | 36 | def visit_blocks(mba: mba_t): 37 | for i in range(mba.qty): 38 | mblock = mba.get_mblock(i) 39 | yield mblock 40 | 41 | 42 | def debug_mode(path): 43 | logger = logging.getLogger("OBPO") 44 | logger.setLevel(logging.DEBUG) 45 | logger.addHandler(logging.FileHandler(path)) 46 | 47 | 48 | def prepare_mc(funcs, level): 49 | x = [] 50 | try: 51 | mbr = mba_ranges_t() 52 | hf = hexrays_failure_t() 53 | ml = mlist_t() 54 | for ea in funcs: 55 | start = int(ea) 56 | end = start + len(funcs[ea]) 57 | mbr.ranges.push_back(range_t(start, end)) 58 | mba = gen_microcode(mbr, hf, ml, DECOMP_WARNINGS, level) 59 | x.append(mba) 60 | except: 61 | pass 62 | for ea in funcs: 63 | x.append(_safe_call(lambda: decompile(int(ea)))) 64 | return x 65 | 66 | 67 | seg_class = {SEG_CODE: "CODE", 68 | SEG_DATA: "DATA", 69 | SEG_BSS: "BSS", 70 | SEG_XTRN: "XTRN", 71 | SEG_COMM: "COMM", 72 | SEG_ABSSYM: "ABS"} 73 | 74 | 75 | def create_segments(segments): 76 | for seg in segments: 77 | sclass = seg["sclass"] 78 | sclass = seg_class[sclass] if sclass in seg_class else "UNK" 79 | add_segm(seg["para"], seg["start"], seg["end"], seg["name"], sclass) 80 | segm = getseg(seg["start"]) 81 | set_segm_base(segm, seg["base"]) 82 | set_segm_attr(segm.start_ea, SEGATTR_PERM, seg["perm"]) 83 | set_segm_alignment(segm.start_ea, seg["align"]) 84 | set_segm_type(segm.start_ea, seg["type"]) 85 | if seg["addressing"]: 86 | set_segm_addressing(segm.start_ea, seg["addressing"]) 87 | auto_wait() 88 | del_items(segm.start_ea) 89 | 90 | 91 | def create_func(func_bytes, T): 92 | for ea in func_bytes: 93 | bs = base64.b64decode(func_bytes[ea]) 94 | ea = int(ea) 95 | end = ea + len(bs) 96 | patch_bytes(ea, bs) 97 | del_items(ea) 98 | auto_wait() 99 | if ea in T: 100 | ea &= ~1 101 | split_sreg_range(ea, "T", 1, SR_user) 102 | auto_make_code(ea) 103 | auto_wait() 104 | add_func(ea, end) 105 | auto_wait() 106 | 107 | 108 | def finder_hooks(finder): 109 | orig_explore = finder._finder_by_explore 110 | 111 | def explore_hook(): 112 | incomplete = orig_explore() 113 | if incomplete: 114 | warning("explore is incomplete and uses aggressive exploration technology. \n" 115 | "[!] note that the control flow may be wrong") 116 | return incomplete 117 | 118 | finder._finder_by_explore = explore_hook 119 | 120 | 121 | def emufinder_hooks(): 122 | orig_emufinder_run = EmuPathFinder.run 123 | 124 | def emufinder_run_hook(self): 125 | res = orig_emufinder_run(self) 126 | if not self.results: 127 | warning("cannot found succs for {}".format(hex(self.source.blk.start))) 128 | return res 129 | 130 | EmuPathFinder.run = emufinder_run_hook 131 | 132 | 133 | def patcher_hooks(patcher): 134 | orig_run = patcher.run 135 | orig_id4case = patcher._id4case 136 | 137 | def run_hook(edge, flows): 138 | success = orig_run(edge, flows) 139 | if not success: 140 | _from = hex(edge.src.start) 141 | _to = {hex(flow.dest_block.start) for flow in flows} 142 | warning("cannot patch edges from {} to {}".format(_from, _to)) 143 | return success 144 | 145 | def id4case_hook(flows): 146 | result = orig_id4case(flows) 147 | if result is None: 148 | _from = {hex(flow.edge.src.start) for flow in flows} 149 | flows = [flow for flow in flows if flow.dest_block != flow.start_block] 150 | result = orig_id4case(flows) 151 | if result: 152 | warning("cut fake branch for {} to {}".format(_from, _from)) 153 | if result is None: 154 | _from = {hex(flow.edge.src.start) for flow in flows} 155 | _to = {hex(flow.dest_block.start) for flow in flows} 156 | warning("cannot found cases id for {} to {}".format(_from, _to)) 157 | return result 158 | 159 | patcher.run = run_hook 160 | patcher._id4case = id4case_hook 161 | 162 | 163 | def prepare(): 164 | task_path = ARGV[1] 165 | task = open(task_path).read() 166 | task = json.loads(task) 167 | create_segments(task["segments"]) 168 | create_func(task["func"], task["t"]) 169 | return task 170 | 171 | 172 | def main(): 173 | # Prepare environment for microcode 174 | debug_mode(os.path.join(TASK_DIR, "log.txt")) 175 | task = prepare() 176 | x = prepare_mc(task["func"], task["maturity"]) # save decompile references to avoid some crash 177 | mba: mba_t = mba_t_deserialize(base64.b64decode(task['mba'])) 178 | if mba is None: 179 | error("load mba failed.") 180 | return 181 | 182 | # Dispatch Analysis 183 | analyzer = DispatchAnalyzer(mba=mba) 184 | for ea in task["dispatchers"]: 185 | try: 186 | analyzer.mark_dispatcher(ea) 187 | except AssertionError as e: 188 | warning(str(e)) 189 | try: 190 | analyzer.run() 191 | except: 192 | error("cannot to analysis dispatcher") 193 | return 194 | 195 | # Real Control Flow Finder 196 | emufinder_hooks() 197 | finder = FlowFinder(analyzer) 198 | finder_hooks(finder) 199 | try: 200 | finder.run() 201 | except: 202 | logging.getLogger("OBPO").exception("exception in flow finder") 203 | warning("exception in flow finder, the control flow maybe wrong") 204 | 205 | # Recovering Control Flow Edges 206 | SplitCommonPatcher(finder).run() 207 | patcher = FlowPatcher(analyzer) 208 | patcher_hooks(patcher) 209 | try: 210 | for edge, flows in finder.edge4flows().items(): 211 | patcher.run(edge, flows) 212 | except: 213 | logging.getLogger("OBPO").exception("exception in flow patcher") 214 | warning("exception in flow patcher, the code maybe not clean") 215 | 216 | # Clear graph to bypass verify mba 217 | for b in visit_blocks(mba): 218 | if b.type == BLT_STOP: 219 | b.make_lists_ready() 220 | continue 221 | if b.type == BLT_XTRN or b.serial == 0: continue 222 | b.type = BLT_NONE 223 | b.mark_lists_dirty() 224 | 225 | result = base64.b64encode(mba.serialize()) 226 | with open(os.path.join(os.path.dirname(TASK_PATH), "mba"), "w") as out: 227 | out.write(result.decode()) 228 | return mba 229 | 230 | 231 | auto_wait() 232 | mba = main() 233 | exit() 234 | -------------------------------------------------------------------------------- /process.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "io/ioutil" 9 | "os" 10 | "os/exec" 11 | "path/filepath" 12 | "strconv" 13 | "time" 14 | ) 15 | 16 | type ArchName string 17 | 18 | const ( 19 | ARM ArchName = "ARM" 20 | METAPC ArchName = "metapc" 21 | ) 22 | 23 | const errorsPath = "errors" 24 | 25 | func init() { 26 | err := os.Mkdir(errorsPath, 0555) 27 | if err != nil { 28 | fmt.Println(err.Error()) 29 | } 30 | } 31 | 32 | type TaskArch struct { 33 | Arch ArchName 34 | Bit int 35 | Version string 36 | } 37 | 38 | func GetOBPOScriptPath() string { 39 | path := os.Getenv("OBPO_PATH") 40 | if path != "" { 41 | return path 42 | } 43 | path = "obpo_script.py" 44 | _, err := os.Stat(path) 45 | if os.IsExist(err) { 46 | return path 47 | } 48 | panic("Cannot found OBPO_PATH.") 49 | } 50 | 51 | func GetOBPOTimeout() int { 52 | env := os.Getenv("OBPO_TIMEOUT") 53 | if env != "" { 54 | timeout, err := strconv.Atoi(env) 55 | if err == nil { 56 | return timeout 57 | } 58 | } 59 | return 60 60 | } 61 | 62 | func getArchBinary(arch TaskArch) string { 63 | if arch.Arch == ARM { 64 | if arch.Bit == 32 { 65 | return filepath.Join(arch.Version, "main_arm.idb") 66 | } else { 67 | return filepath.Join(arch.Version, "main_arm64.i64") 68 | } 69 | } else if arch.Arch == METAPC { 70 | if arch.Bit == 32 { 71 | return filepath.Join(arch.Version, "main_x86.idb") 72 | } else { 73 | return filepath.Join(arch.Version, "main_x86_64.i64") 74 | } 75 | } 76 | return "" 77 | } 78 | 79 | func fileCopy(src string, dest string) error { 80 | bytesRead, err := ioutil.ReadFile(src) 81 | 82 | if err != nil { 83 | return err 84 | } 85 | 86 | err = ioutil.WriteFile(dest, bytesRead, 0644) 87 | 88 | return err 89 | } 90 | 91 | func makeErrorResponse(code int, error string) Response { 92 | return Response{ 93 | Code: code, 94 | Error: error, 95 | Warn: "", 96 | Data: ResultData{}, 97 | } 98 | } 99 | 100 | func prepareIdb(dir string, arch TaskArch) (string, error) { 101 | binary := getArchBinary(arch) 102 | _, err := os.Stat(binary) 103 | if binary == "" || err != nil { 104 | return "", errors.New( 105 | fmt.Sprintf("unsupported current hexrays version(%s) or architecture(%s:%d), "+ 106 | "please see: github.com/obpo-project/obpo-plugin", arch.Version, arch.Arch, arch.Bit)) 107 | } 108 | 109 | idbPath := filepath.Join(dir, "binary") 110 | if arch.Bit == 64 { 111 | idbPath += ".i64" 112 | } else { 113 | idbPath += ".idb" 114 | } 115 | err = fileCopy(binary, idbPath) 116 | if err != nil { 117 | println("Copy binary error: " + err.Error()) 118 | return "", errors.New("server internal error") 119 | } 120 | return idbPath, err 121 | } 122 | 123 | func prepareObpo(dir string) (string, error) { 124 | scriptPath := filepath.Join(dir, "obpo_script.py") 125 | err := fileCopy(GetOBPOScriptPath(), scriptPath) 126 | if err != nil { 127 | println("Copy script error: " + err.Error()) 128 | return "", errors.New("server internal error") 129 | } 130 | return scriptPath, err 131 | } 132 | 133 | func prepareTask(dir string, request string) (string, error) { 134 | taskPath := filepath.Join(dir, "task.json") 135 | err := ioutil.WriteFile(taskPath, []byte(request), 0555) 136 | if err != nil { 137 | println("Write task error: " + err.Error()) 138 | return "", errors.New("server internal error") 139 | } 140 | return taskPath, err 141 | } 142 | 143 | func startTask(arch TaskArch, inputFile string, obpoPath string, taskPath string) error { 144 | idaPath := filepath.Join(arch.Version, "idapro", "ida.exe") 145 | if arch.Bit == 64 { 146 | idaPath = filepath.Join(arch.Version, "idapro", "ida64.exe") 147 | } 148 | 149 | ctxt, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(GetOBPOTimeout())) 150 | defer cancel() 151 | cmd := exec.CommandContext(ctxt, idaPath, "-A", fmt.Sprintf("-S%s %s", obpoPath, taskPath), inputFile) 152 | _ = append(cmd.Env, fmt.Sprintf("JSON_PATH=%s", taskPath)) 153 | err := cmd.Run() 154 | if ctxt.Err() == context.DeadlineExceeded { 155 | return errors.New("process timeout") 156 | } 157 | if err != nil && err.Error() != "exit status 1" { 158 | println("Command error: " + err.Error()) 159 | return errors.New("obpo except exit") 160 | } 161 | return nil 162 | } 163 | 164 | func fileContent(path string) string { 165 | bytesRead, err := ioutil.ReadFile(path) 166 | if err != nil { 167 | return "" 168 | } 169 | return string(bytesRead) 170 | } 171 | 172 | func makeResponse(dir string, err error) Response { 173 | errorMsg := fileContent(filepath.Join(dir, "error")) 174 | warnMsg := fileContent(filepath.Join(dir, "warn")) 175 | mba := fileContent(filepath.Join(dir, "mba")) 176 | code := 0 177 | if mba == "" { 178 | code = -6 179 | } 180 | if err != nil { 181 | errorMsg = err.Error() + "\n" + errorMsg 182 | } 183 | return Response{ 184 | Code: code, 185 | Error: errorMsg, 186 | Warn: warnMsg, 187 | Data: ResultData{Mba: mba}, 188 | } 189 | 190 | } 191 | 192 | func process(requestJson string) (response Response) { 193 | taskArch := TaskArch{} 194 | err := json.Unmarshal([]byte(requestJson), &taskArch) 195 | if err != nil { 196 | return makeErrorResponse(-1, "Unable to unmarshal request.") 197 | } 198 | 199 | tmpDir, err := ioutil.TempDir("", "obpo") 200 | if err != nil { 201 | println("Create tmpdir error: " + err.Error()) 202 | return makeErrorResponse(-2, "Server internal error.") 203 | } 204 | 205 | defer func() { 206 | _ = os.RemoveAll(tmpDir) 207 | if response.Code == 0 || len(requestJson) > 1024*1024*2 { 208 | return 209 | } 210 | 211 | id := time.Now().Unix() 212 | path := filepath.Join(errorsPath, fmt.Sprintf("%d_%d.json", response.Code, id)) 213 | _ = ioutil.WriteFile(path, []byte(requestJson), 0555) 214 | 215 | path = filepath.Join(errorsPath, fmt.Sprintf("%d_%d.err", response.Code, id)) 216 | _ = ioutil.WriteFile(path, []byte(response.Error), 0555) 217 | }() 218 | 219 | idbPath, err := prepareIdb(tmpDir, taskArch) 220 | if err != nil { 221 | return makeErrorResponse(-3, err.Error()) 222 | } 223 | 224 | obpoPath, err := prepareObpo(tmpDir) 225 | if err != nil { 226 | return makeErrorResponse(-4, err.Error()) 227 | } 228 | 229 | taskPath, err := prepareTask(tmpDir, requestJson) 230 | if err != nil { 231 | return makeErrorResponse(-5, err.Error()) 232 | } 233 | 234 | err = startTask(taskArch, idbPath, obpoPath, taskPath) 235 | 236 | return makeResponse(tmpDir, err) 237 | } 238 | --------------------------------------------------------------------------------